Lombok Value annotation (@Value) is used when creating Immutable classes. All Lombok generated fields are made private
and final
by default, and setters are not generated. The class itself is also made final
by default.
Make sure you already installed Lombok setup for your IDE. To Setup in Eclipse or in Spring Tool Suite refer to our Lombok Maven example setup with Eclipse.
1. What is Lombok @Value annotation?
@Value annotation is short hand for the annotation combination @Getter
@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE)
@AllArgsConstructor
@ToString
@EqualsAndHashCode
.
Following side by side code demonstrates simple usage of Lombok’s @Value
annotation and how looks like Lombok generated code exactly when you use @Value
annotation.
Lomboked User1.java
@Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @AllArgsConstructor @ToString @EqualsAndHashCode public final class User1 { private Long id; private String username; }
Lomboked User2.java
@Value public class User2 { private Long id; private String username; }
Now let’s have a look into Lombok generated (Delomboked) code for both classes.
DeLomboked User1.java
public final class User1 { private final Long id; private final String username; public Long getId() { return this.id; } public String getUsername() { return this.username; } public User1(final Long id, final String username) { this.id = id; this.username = username; } @Override public String toString() { return "User1(id=" + this.getId() + ", username=" + this.getUsername() + ")"; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof User1)) return false; final User1 other = (User1) o; final Object this$id = this.getId(); final Object other$id = other.getId(); if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false; final Object this$username = this.getUsername(); final Object other$username = other.getUsername(); if (this$username == null ? other$username != null : !this$username.equals(other$username)) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final Object $id = this.getId(); result = result * PRIME + ($id == null ? 43 : $id.hashCode()); final Object $username = this.getUsername(); result = result * PRIME + ($username == null ? 43 : $username.hashCode()); return result; } }
DeLomboked User2.java
public final class User2 { private final Long id; private final String username; public User2(final Long id, final String username) { this.id = id; this.username = username; } public Long getId() { return this.id; } public String getUsername() { return this.username; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof User2)) return false; final User2 other = (User2) o; final Object this$id = this.getId(); final Object other$id = other.getId(); if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false; final Object this$username = this.getUsername(); final Object other$username = other.getUsername(); if (this$username == null ? other$username != null : !this$username.equals(other$username)) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final Object $id = this.getId(); result = result * PRIME + ($id == null ? 43 : $id.hashCode()); final Object $username = this.getUsername(); result = result * PRIME + ($username == null ? 43 : $username.hashCode()); return result; } @Override public String toString() { return "User2(id=" + this.getId() + ", username=" + this.getUsername() + ")"; } }
2. Lombok @Data vs @Value
The Lombok @Value and Lombok @Data both annotations generate boilerplate code related to POJO items, one key difference is @Value annotation is used to make your classes immutable. By seeing above examples we can notice following differences.
@Data | @Value |
---|---|
Lombok generated class is not final . | Lombok generated class is final . |
Generates required-args constructor. | Generates all-args constructor. |
Generates equals(), hashCode() and toString(). | Generates equals(), hashCode() and toString(). |
Does not make fields final . | Makes all non-static fields final . |
Generates setters and getters. No getters/setters are generated for static fields and no setters generate for final fields. | No setters generate for any filed as it makes all fields final except static fields, and obviously no getters generate for static fileds. |
4. @Value staticConstructor
If you specify a staticConstructor name, then the generated constructor will be private
, a static factory method is created to that other classes can use to create instances.
Lomboked User3.java
@Value(staticConstructor = "getInstance") public class User3 { private Long id; private String username; }
DeLomboked User3.java
public final class User3 { private final Long id; private final String username; private User3(final Long id, final String username) { this.id = id; this.username = username; } public static User3 getInstance(final Long id, final String username) { return new User3(id, username); } // Rest of code same as delomboked User2.java }
5. Lombok @Value ignore/exclude fields
@Value annotation alone not provide support for ignoring fields from generating getters or toString or equals and hashCode methods. Following example demonstrates how to exclude fields when you are using @Value annotation.
@Value public class User4 { private Long id; @Getter(value = AccessLevel.NONE) private String username; @ToString.Exclude private boolean active; @EqualsAndHashCode.Exclude @ToString.Exclude private int role; }
6. Lombok @Value and @Builder together with default values
Following example demonstrates how to use @Value and @Builder together and to set default values. Note that all-args constructor access level changed public to package.
import lombok.Builder; import lombok.Builder.Default; import lombok.Value; @Builder @Value public class User5 { private Long id; private String username; @Default private boolean active = true; @Default private int role = 3; }
Testing User5 :
public class User5Test { public static void main(String[] args) { User5 user5 = User5.builder().build(); System.out.println("user5 => "+user5); User5 user51 = User5.builder() .active(false) .id(Long.valueOf(1)) .role(4) .username("Peter") .build(); System.out.println("user51 => "+user51); } }
Output Results :
user5 => User5(id=null, username=null, active=true, role=3) user51 => User5(id=1, username=Peter, active=false, role=4)
7. Making class and fields non final
It is possible to change default behavior of @Value to not make class and fields non-final using @NonFinal, but the class lost immutable nature.
@Value @Setter @NonFinal public class User6 { private Long id; @NonFinal private String username; public final String defaultStatus = "inactive"; public static int defaultRole = 2; }
You can see delomboked code for this example at our GitHub repository.
Conclusion
We have covered in this article what is Lombok value annotation (@Value
), how do we use it in java with a simple example by differentiating lombok generated code. You can refer Delombok Maven example to see how looks like lombok generated code for your Lomboked classes.
You can checkout source code from our github repository.
You might be interested in our other following Lombok Tutorials :
- Lombok @Getter @Setter and lazy getters
- Lombok @Builder
- Lombok @Builder.Default
- Lombok @Singular
- Lombok @NonNull
- Lombok Spring Boot example