jade-recipe-11-17-wrapper-valueof
Replaces primitive wrapper constructor calls with the corresponding valueOf factory. JEP 390 (JDK 16) deprecated those constructors for removal. Agent-mode recipe: the shard contract names the files;
SKILL.md.claude/skills/java-migration-skill-registry/11-to-17/jade-recipe-11-17-wrapper-valueof/SKILL.md
GitHubjade-recipe-11-17-wrapper-valueof — the wrapper constructors are on the way out
JEP 390 designated the primitive wrapper classes as value-based and deprecated their constructors for removal. The JDK 16 release note is explicit: "Programmers are strongly discouraged from calling the wrapper class constructors, which are now deprecated for removal."
Nothing is broken on JDK 17 — the code compiles and runs. What the rule buys is
that this is JADE's largest terminally-deprecated surface: 144 sites confirmed
by javac itself (-Xlint:removal -Xmaxwarns 100000), spread over 52 files.
Scope of one task
You receive a shard contract. This rule is blast_class: body-local
(parallel_safe: true), planned into 12 shards. Edit only that shard's
editable_files; read_only_context is read-only.
The transform
new Boolean(x) -> Boolean.valueOf(x)
new Integer(x) -> Integer.valueOf(x)
new Long(x) -> Long.valueOf(x)
new Double(x) -> Double.valueOf(x)
new Float(x) -> Float.valueOf(x)
new Character(c) -> Character.valueOf(c)
Both the primitive and the String overloads are covered — Integer.valueOf(String)
and Long.valueOf(String) exist and parse identically. Fully-qualified receivers
(new java.lang.Long(...)) keep their qualification: java.lang.Long.valueOf(...).
The static type of the expression is unchanged, so no field type, method signature or return type moves. That is what makes this body-local.
The one thing that can go wrong
valueOf may return a cached, shared instance where the constructor always
returned a fresh one. Boolean.valueOf always returns Boolean.TRUE or
Boolean.FALSE; Integer.valueOf, Long.valueOf, Short.valueOf and
Byte.valueOf intern -128..127; Character.valueOf interns 0..127.
Before converting a site, check what happens to the resulting object:
- compared with
==or!=against another wrapper - used as a
synchronizedmonitor - used as a key in an
IdentityHashMap, or passed toSystem.identityHashCode - relied on for
wait/notify
Any of those makes the conversion a behaviour change. Leave the site as it is,
keep its // JADE-FLAG: marker, and report it in the shard result. Converting
an identity-sensitive site is worse than leaving a deprecation warning.
.equals comparison, .intValue()/.booleanValue() unwrapping, storage in a
collection, and use as a method argument are all safe.
What the agent may not do
- Do not "simplify" further by removing the boxing altogether (
new Integer(x)->x). Autoboxing has different overload-resolution behaviour and this rule is not a refactor. - Do not edit a site inside a comment or a string literal. The scanner's line
filter is prefix-based and its population (147) is three larger than javac's
live count (144); the difference is code sitting inside block comments such as
MMCanvas.java:427-469. Check withjava_source.is_live_code()before every edit. - Do not touch
#PJAVA_INCLUDE,#DOTNET_INCLUDEor#MIDP_EXCLUDEblocks. They are comment text, not code.
Verification
Recompiling in jade-ant:17 with -Xlint:removal -Xmaxwarns 100000 reports zero
[removal] ... in Boolean/Integer/Long/Double/Float/Character has been deprecated and marked for removal warnings, down from 144. Any site deliberately left
behind is named in the shard result with its reason. The build exits 0 and all
consumers PASS.