From 56150952c451f0d8c2018424191d4480ac5e8460 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot
NEW in lombok 0.10: You can annotate any class with a log annotation to let lombok generate a logger field.
- There are four choices available:Overview
- The logger is named log
and field's type depends on which logger you have selected.
+ The logger is named log
and the field's type depends on which logger you have selected.
+ There are six choices available:
@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
e.printStackTrace()
in the catch block. This is so spectacularly non-productive
compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the
checked exception system is far from perfect, and thus an opt-out mechanism is warranted.
-
+ If you put @SneakyThrows
on a constructor, any call to a sibling or super constructor is excluded from the @SneakyThrows
treatment. This is a
+ java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks.
+
+ @SneakyThrows
on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.
lombok.jar
in your IDE, you can also check out the javadoc.
diff --git a/website/index.html b/website/index.html
index edce2a2d..dcac3ab5 100644
--- a/website/index.html
+++ b/website/index.html
@@ -87,7 +87,7 @@
types
or excludes
parameter, you cannot include generics.
This is a limitation of java. Use private inner interfaces or classes that extend the intended type including the
generics parameter to work around this problem.
-
- +
When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example. -
-+
@Delegate
cannot be used on static fields or methods.
-
+ NEW in Lombok 0.11.10: You can use @NonNull
on the parameter of a method or constructor to have lombok generate a null-check statement for you.
+
+ Lombok has always treated any annotation named @NonNull
on a field as a signal to generate a null-check if lombok generates an entire method or constructor for you, via
+ for example @Data
. Now, however, using lombok's own @lombok.NonNull
on a parameter results in the insertion of just the null-check
+ statement inside your own method or constructor.
+
+ The null-check looks like if (param == null) throw new NullPointerException("param");
and will be inserted at the very top of your method. For constructors, the null-check
+ will be inserted immediately following any explicit this()
or super()
calls.
+
+ If a null-check is already present at the top, no additional null-check will be generated. +
+
+ Lombok's detection scheme for already existing null-checks consists of scanning for if statements that look just like lombok's own. Any 'throws' statement as
+ the 'then' part of the if statement, whether in braces or not, counts. The conditional of the if statement must look exactly like PARAMNAME == null
.
+ The first statement in your method that is not such a null-check stops the process of inspecting for null-checks.
+
+ While @Data
and other method-generating lombok annotations will trigger on any annotation named @NonNull
regardless of casing or package name,
+ this feature only triggers on lombok's own @NonNull
annotation from the lombok
package.
+
+ A @NonNull
on a primitive parameter results in a warning. No null-check will be generated.
+
- @SneakyThrows
is an implementation of this feature request: http://bugs.sun.com/view_bug.do?bug_id=6534270.
-
Because @SneakyThrows
is an implementation detail and not part of your method signature, it is an error if you try to
declare a checked exception as sneakily thrown when you don't call any methods that throw this exception. (Doing so is perfectly legal
for throws
statements to accommodate subclasses). Similarly, @SneakyThrows
does not inherit.
@@ -72,7 +70,7 @@
val
@NonNull
@Cleanup
close()
methods safely with no hassle.@Getter
/ @Setter
public int getFoo() {return foo;}
again.@Getter(lazy=true)
@ToString
toString
for you!@EqualsAndHashCode
@Data
@ToString
, @EqualsAndHashCode
,
@Getter
on all fields, and @Setter
on all non-final fields, and @RequiredArgsConstructor
!@Cleanup
close()
methods safely with no hassle.@Synchronized
synchronized
done right: Don't expose your locks.@SneakyThrows
@Synchronized
synchronized
done right: Don't expose your locks.@Getter(lazy=true)
@Log
val
@Delegate
+ @Builder was introduced as experimental feature in lombok v0.11.10. +
++ Experimental because: +
+ The @Builder
annotation produces complex builder APIs for your classes.
+
+ @Builder
lets you automatically produce the code required to have your class be instantiable with code such as:
+ Person.builder().name("Adam Savage").city("San Francisco").worksAt("Mythbusters").build();
+
+ @Builder
can be placed on a class, or on a constructor, or on a static method. While the "on a class" and "on a constructor"
+ mode are the most common use-case, @Builder
is most easily explained with the "static method" use-case.
+
+ A static method annotated with @Builder
(from now on called the target) causes the following 7 things to be generated:
FooBuilder
, with the same type arguments as the static method (called the builder).build()
method which calls the static method, passing in each field. It returns the same type that the
+ target returns.toString()
implementation.builder()
method, which creates a new instance of the builder.
+ Now that the "static method" mode is clear, putting a @Builder
annotation on a constructor functions similarly; effectively,
+ constructors are just static methods that have a special syntax to invoke them: Their 'return type' is the class they construct, and their
+ type parameters are the same as the type parameters of the class itself.
+
+ Finally, applying @Builder
to a class is as if you added @AllArgsConstructor(acces = AccessLevel.PACKAGE)
to the class and applied the
+ @Builder
annotation to this all-args-constructor. Note that this constructor is only generated if there is no explicit
+ constructor present in the so annotated class, but this @AllArgsConstructor
has priority over any other implicitly
+ generated lombok constructor (such as @Data
and @Value
). If an explicit constructor is present, no constructor is generated,
+ but the builder will be created with the assumption that this constructor exists. If you've written another constructor, you'll get a compilation error.
+ The solution is to either let lombok write this constructor (delete your own), or, annotate your constructor instead.
+
+ The name of the builder class is FoobarBuilder
, where Foobar is the simplified, title-cased form of the return type of the
+ target - that is, the name of your type for @Builder
on constructors and types, and the name of the return type for @Builder
+ on static methods. For example, if @Builder
is applied to a class named com.yoyodyne.FancyList<T>
, then the builder name will be
+ FancyListBuilder<T>
. If @Builder
is applied to a static method that returns void
, the builder will be named
+ VoidBuilder
.
+
+ The only configurable aspect of builder are the builder's class name (default: return type + 'Builder'), the build() method's name, and the
+ builder() method's name:
+ @Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld")
+
+ Another strategy for fluent APIs is that the programmer using your library statically imports your 'builder' method. In this case, you might want to name your builder
+ method equal to your type's name. So, the builder method for a class called Person
would become person()
. This is nicer if the builder method
+ is statically imported.
+
+ If the return type of your target static method is a type parameter (such as T
), lombok will enforce an explicit builder class name.
+
+ You don't HAVE to use @Builder
to build anything; you can for example put it on a static method that has lots of parameter to improve the API of it.
+ In this case, we suggest you use buildMethodName =
to rename the build method to execute()
instead.
+
+ The builder class will NOT get an auto-generated implementation of hashCode
or equals
methods! These would suggest that it is sensible to use
+ instances of a builder as keys in a set or map. However, that's not a sensible thing to do. Hence, no hashCode
or equals
.
+
+ Generics are sorted out for you. +
+@Builder
@Accessors
@ExtensionMethod
+ * Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @RequiredArgsConstructor @ToString @EqualsAndHashCode}. + *
+ * Complete documentation is found at the project lombok features page for @Value. + * + * @see lombok.Getter + * @see lombok.experimental.FieldDefaults + * @see lombok.RequiredArgsConstructor + * @see lombok.ToString + * @see lombok.EqualsAndHashCode + * @see lombok.Data + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface Value { + /** + * If you specify a static constructor name, then the generated constructor will be private, and + * instead a static factory method is created that other classes can use to create instances. + * We suggest the name: "of", like so: + * + *
+ * public @Data(staticConstructor = "of") class Point { final int x, y; } + *+ * + * Default: No static constructor, instead the normal constructor is public. + */ + String staticConstructor() default ""; +} diff --git a/src/core/lombok/core/LombokInternalAliasing.java b/src/core/lombok/core/LombokInternalAliasing.java new file mode 100644 index 00000000..4fd7b29d --- /dev/null +++ b/src/core/lombok/core/LombokInternalAliasing.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.core; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class LombokInternalAliasing { + public static final Map
+ @Value
was introduced as experimental feature in lombok v0.11.4.
+
+ @Value
no longer implies @Wither
since lombok v0.11.8.
+
+ @Value
promoted to the main lombok
package since lombok v0.11.10.
+
+ @Value
is the immutable variant of @Data
; all fields are made private
and final
by default, and setters are not generated. The class itself is also made final
by default, because immutability is not something that can be forced onto a subclass. Like @Data
, useful toString()
, equals()
and hashCode()
methods are also generated, each field gets a getter method, and a constructor that covers every
+ argument (except final
fields that are initialized in the field declaration) is also generated.
+
+ In practice, @Value
is shorthand for: final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
.
+
+ It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the @NonFinal
or @PackagePrivate
annotations.
+ It is possible to override any default behaviour for any of the 'parts' that make up @Value
by explicitly using that annotation.
+
+ Look for the documentation on the 'parts' of @Value
: @ToString
, @EqualsAndHashCode
, @AllArgsConstructor
, @FieldDefaults
, and @Getter
.
+
+ For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit @AllArgsConstructor(staticConstructor="of")
annotation, there's also the @Value(staticConstructor="of")
feature, which will make the generated all-arguments constructor private, and generates a public static method named of
which is a wrapper around this private constructor.
+
+ @Value
was an experimental feature from v0.11.4 to v0.11.9 (as @lombok.experimental.Value
). It has since been moved into the core package. The old annotation is still
+ around (and is an alias). It will eventually be removed in a future version, though.
+
- @Value
was introduced as experimental feature in lombok v0.11.4.
-
- @Value
no longer implies @Wither
since lombok v0.11.8.
-
- Experimental because: -
- @Value
is the immutable variant of @Data
; all fields are made private
and final
by default, and setters are not generated. The class itself is also made final
by default, because immutability is not something that can be forced onto a subclass. Like @Data
, useful toString()
, equals()
and hashCode()
methods are also generated, each field gets a getter method, and a constructor that covers every
- argument (except final
fields that are initialized in the field declaration) is also generated.
-
- In practice, @Value
is shorthand for: final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
.
-
- It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the @NonFinal
or @PackagePrivate
annotations.
- It is possible to override any default behaviour for any of the 'parts' that make up @Value
by explicitly using that annotation.
-
- Look for the documentation on the 'parts' of @Value
: @ToString
, @EqualsAndHashCode
, @AllArgsConstructor
, @FieldDefaults
, and @Getter
.
-
- For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit @AllArgsConstructor(staticConstructor="of")
annotation, there's also the @Value(staticConstructor="of")
feature, which will make the generated all-arguments constructor private, and generates a public static method named of
which is a wrapper around this private constructor.
-
@Wither
@Value
onMethod= / onConstructor= / onParam
@Value
: Promoted@Value
has proven its value and has been moved to the main package.
+ @Data
@ToString
, @EqualsAndHashCode
,
@Getter
on all fields, and @Setter
on all non-final fields, and @RequiredArgsConstructor
!@Value
@SneakyThrows
@Synchronized
- NEW IN Lombok 0.10: You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful
- if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a private final
variable,
- initialize it with the expression that's expensive to run, and annotate your field with @Getter(lazy=true)
. The field will be hidden from the
- rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even
- if the result of your expensive calculation is null
, the result is cached) and your expensive calculation need not be thread-safe, as lombok
- takes care of locking.
+ NEW IN Lombok 0.10: You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a private final
variable, initialize it with the expression that's expensive to run, and annotate your field with @Getter(lazy=true)
. The field will be hidden from the rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even if the result of your expensive calculation is null
, the result is cached) and your expensive calculation need not be thread-safe, as lombok takes care of locking.
- Lombok actually creates a few fields all prefixed with $lombok$
to cache the value. You should not rely on the exact type, name, and structure
- of these fields as future implementations may change them. To access the lazily initialized value, always use the generated getter.
+ You should never refer to the field directly, always use the getter generated by lombok, because the type of the field will be mangled into an AtomicReference
. Do not try to directly access this AtomicReference
; if it points to itself, the value has been calculated, and it is null
. If the reference points to null
, then the value has not been calculated. This behaviour may change in future versions. Therefore, always use the generated getter to access your field!
Other Lombok annotations such as @ToString
always call the getter even if you use doNotUseGetters=true
.
@Getter
, @Setter
or @Data
annotation on a class.
To put annotations on the generated method, you can use onMethod=@_({@AnnotationsHere})
; to put annotations on the only parameter of a generated setter method, you can use onParam=@_({@AnnotationsHere})
. Be careful though! This is an experimental feature. For more details see the documentation on the onX feature.
+
+ NEW in lombok v1.12.0: javadoc on the field will now be copied to generated getters and setters. Normally, all text is copied, and @return
is moved to the getter, whilst @param
lines are moved to the setter. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for each getter/setter. To do that, you create a 'section' named GETTER
and/or SETTER
. A section is a line in your javadoc containing 2 or more dashes, then the text 'GETTER' or 'SETTER', followed by 2 or more dashes, and nothing else on the line. If you use sections, @return
and @param
stripping for that section is no longer done (move the @return
or @param
line into the section).
To put annotations on the generated method, you can use onMethod=@_({@AnnotationsHere})
; to put annotations on the only parameter of a generated wither method, you can use onParam=@_({@AnnotationsHere})
. Be careful though! This is an experimental feature. For more details see the documentation on the onX feature.
+
+ NEW in lombok v1.12.0: javadoc on the field will now be copied to generated withers. Normally, all text is copied, and @param
is moved to the wither, whilst @return
lines are stripped from the wither's javadoc. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for the wither's javadoc. To do that, you create a 'section' named WITHER
. A section is a line in your javadoc containing 2 or more dashes, then the text 'WITHER', followed by 2 or more dashes, and nothing else on the line. If you use sections, @return
and @param
stripping / copying for that section is no longer done (move the @param
line into the section).
+ * Default: true + */ + boolean fluent() default true; + + /** + * Normally the builder's 'set' methods are chaining, meaning, they return the builder so that you can chain + * calls to set methods. Set this to {@code false} to have these 'set' methods return {@code void} instead. + *
+ * Default: true
+ */
+ boolean chain() default true;
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index aa485b26..6422f5ed 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -49,16 +49,19 @@ import com.sun.tools.javac.util.Name;
import lombok.AccessLevel;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.core.TransformationsUtil;
import lombok.experimental.Builder;
+import lombok.experimental.NonFinal;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
-
import static lombok.javac.Javac.*;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleBuilder extends JavacAnnotationHandler
It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the @NonFinal
or @PackagePrivate
annotations.
It is possible to override any default behaviour for any of the 'parts' that make up @Value
by explicitly using that annotation.
-
@Value
was an experimental feature from v0.11.4 to v0.11.9 (as @lombok.experimental.Value
). It has since been moved into the core package. The old annotation is still
around (and is an alias). It will eventually be removed in a future version, though.
+
+ It is not possible to use @FieldDefaults
to 'undo' the private-by-default and final-by-default aspect of fields in the annotated class. Use @NonFinal
and @PackagePrivate
on the fields in the class to override this behaviour.
+
@Builder
@Accessors
@ExtensionMethod
@Value
no longer implies @Wither
since lombok v0.11.8.
- @Value
promoted to the main lombok
package since lombok v0.11.10.
+ @Value
promoted to the main lombok
package since lombok v0.12.0.
- @Builder was introduced as experimental feature in lombok v0.11.10. + @Builder was introduced as experimental feature in lombok v0.12.0.