@Wither was introduced as experimental feature in lombok v0.11.4.
Experimental because:
@Wither
is an appropriate name for this feature.
The next best alternative to a setter for an immutable property is to construct a clone of the object, but with a new value for this one field.
A method to generate this clone is precisely what @Wither
generates: a withFieldName(newValue)
method which produces a clone
except for the new value for the associated field.
For example, if you create public class Point { private final int x, y; }
, setters make no sense because the fields
are final. @Wither
can generate a withX(int newXValue)
method for you which will return a new point with the supplied
value for x
and the same value for y
.
Like @Setter
, you can specify an access level in case you want the generated wither to be something other than public
:
@Wither(level = AccessLevel.PROTECTED)
. Also like @Setter
, you can also put a @Wither
annotation on a type, which means
a 'wither' is generated for each field (even non-final fields).
Withers cannot be generated for static fields because that makes no sense.
When applying @Wither
to a type, static fields and fields whose name start with a $ are skipped.
For generating the method names, the first character of the field, if it is a lowercase character, is title-cased, otherwise, it is left unmodified.
Then, with
is prefixed.
No method is generated if any method already exists with the same name (case insensitive) and same parameter count. For example, withX(int x)
will not be generated if there's already a method withX(String... x)
even though it is technically possible to make the method. This caveat
exists to prevent confusion. If the generation of a method is skipped for this reason, a warning is emitted instead. Varargs count as 0 to N parameters.
For boolean
fields that start with is
immediately followed by a title-case letter, nothing is prefixed to generate the wither name.
Any annotations named @NonNull
(case insensitive) on the field are interpreted as: This field must not ever hold
null. Therefore, these annotations result in an explicit null check in the generated wither. Also, these
annotations (as well as any annotation named @Nullable
or @CheckForNull
) are copied to wither parameter.