6

Using lombok for a project, I have an ArrayList. It's null because it's never initialized. I originally initialized this in the constructor before I decided to use lombok to remove the bulk of boilerplate code.

What's the simplest example of getting it to work?

Example : Calling refresh throws a null pointer after creating a builder (Note: I've omitted variables that are used in the builder, but parameters is not mentioned in the builder so perhaps I need to do something with it).

@Builder
public @Data class RMF_Objective {

   private ArrayList<String> parameters;

   public void refresh(){     
        parameters.clear(); // Clear for now
   }
}
user3000724
  • 651
  • 3
  • 11
  • 22

3 Answers3

4

The simplest initializing it with the Lombok's builder is like this:

    @Builder
    public @Data class RMF_Objective {

        private ArrayList<String> parameters;

        public void refresh() {
            parameters.clear(); // Clear for now
            System.out.println("cleared !");
        }

        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>(Arrays.asList("one", "two"));
            RMF_Objective builtObject = new RMF_ObjectiveBuilder()
                    .parameters(list)
                    .build();
            builtObject.refresh();
        }
    }

Otherwise you could also use Lombok's @Singular annotation to make it generate a 'singular' version of the parameters() method taking only one String as input parameter. Like this:

@Builder
public @Data class RMF_ObjectiveSingular {

    @Singular
    private List<String> parameters;

    public void refresh() {
        parameters.clear(); // Clear for now
        System.out.println("cleared !");
    }

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(Arrays.asList("one", "two"));
        RMF_ObjectiveSingular builtObject = new RMF_ObjectiveSingularBuilder()
                .parameter("one")
                .parameter("two")
                .build();
        builtObject.refresh();
    }
}

But if I were you, I would really use only the @Value's Lombok annotation. If you don't need a builder, it's simpler to have only a constructor initializing the object and Getter but no Setters. Immutables objects are often safer.

Francois Marot
  • 1,145
  • 11
  • 18
2

As per https://reinhard.codes/2016/07/13/using-lomboks-builder-annotation-with-default-values/ using default values in your class won't work.

You can provide a minimal builder implementation containing the default values like:

public static class RMF_ObjectiveBuilder{
    private ArrayList<String> parameters = new ArrayList<>();
}
2

If annotated with @Builder.Default, parameters is initialised:

@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RMF_Objective {

  @Builder.Default private ArrayList<String> parameters = new ArrayList<>();

  public void refresh(){
    parameters.clear(); // Clear for now
  }

}

From the documentation:

@Builder.Default

If a certain field/parameter is never set during a build session, then it always gets 0 / null / false. If you've put @Builder on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with @Builder.Default: @Builder.Default private final long created = System.currentTimeMillis();

Note that:

  • @Data - which includes @RequiredArgsConstructor - has been removed
  • @AllArgsConstructor - included in @Builder - access level has been set to PRIVATE (default is PUBLIC)

This prevents instantiating RMF_Objective via its one-argument constructor such as

new RMF_Objective(null).refresh()

which would throw NullPointerException.

santos
  • 79
  • 3