Lombok @Value annotation

This article will cover lombok @Value annotation in detail, what is its use, its configuration options and overriding its default behaviour with examples.
It will also outline difference between @Value and @Data annotations.

@Value annotation
Lombok @Value annotation is applied over a class and it is a shorter replacement of below annotations:
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@Getter
@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE)

This means that when @Value is written over a class, it generates
A. toString() method
B. equals() and hashCode() methods
C. constructor with all fields as arguments, except those that are not assigned a value at declaration.
D. getter methods for all non-static fields.

Besides this, @Value makes all the non-static fields as private and final, it makes the class as final and does not generate setter method for any of its fields.
In short, it makes the class immutable.
POJO without lombok
Below is a java class having two fields or instance variables, without lombok annotations.

public class User {

  private String name;

  private int age;

  public User(String n, int a) {
    this.name = n;
    this.age = a;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
 
  public boolean equals(Object o) {
    // implementation
  }

  public int hashCode() {
    // implementation
  }

  public String toString() {
    // implementation
  }
}

Above class with lombok @Value annotation will look like

import lombok.Value;

@Value
public class User {

  private String name; 

  private int age;
}

That is all. You can see how concise the class becomes.

@Value Example
Below is an example program that creates an object of the above class annotated with @Value annotation and calls its various methods.

public class ValueDemo {

  public static void main(String[] a) {
    User user = new User();
    user.setName("A");
    user.setAge(22);
    System.out.println("Name is: " +user.getName());
    System.out.println("Age is: " +user.getAge());
    System.out.println("Hashcode is: " +user.getName());
    System.out.println("User as a string: " +user.getName());
  }
}

Name is: A
Age is: 22
Hashcode is: 4844
User as a string: User(name=A, age=22)

Generating private constructor
It is possible to generate a private constructor for a class, and create a static method with public access modifier.
This method will return an object of this class instead of exposing the constructor. Generated method will accept all fields as arguments.
To generate private constructor, use staticConstructor option of @Value providing it the name of the method to generate. Example,

@Value(staticConstructor = "getInstance")
public class User {
   private String name;

   private int age;
}

Now, you can not create an object of this class with new. It will be created as

User user = User.getInstance("A", 22);

Remember that this option has nothing to do with Singleton class. Each time getInstance() is called, a new object will be returned.

@Value configurations
1. Access modifier for all getter/setter methods generated with @Value will be private. To set any other access type, you should write explicit @Getter/@Setter with AccessLevel option.

2. All fields will be final by default. This can be overridden by using @NonFinal annotation on specific fields.

3. @Value also makes the class final. To override this, use @NonFinal annotation at class level.

4. equals() and hashCode() generated with @Value use all the fields of the class. To skip any field, use explicit @EqualsAndHashCode.Exclude over it.

5. Similarly, toString() generated with @Value uses all the fields of the class. To skip any field, use explicit @ToString.Exclude over it.

6. @Value will not generate a constructor if there is already one present in the class.

7. @Value will not generate equals() method, if there is a method with this present in the class.

Hope the article was useful.