Initialize list if list is null with lombok getter?
Asked Answered
W

5

33

I am currently replacing all my standard POJO's to use Lombok for all the boilerplate code. I find myself keeping getters for lists because I want to return an empty list if the list has not been initialized. That is, I don't want the getter to return null. If there some lombok magic that I'm not aware of that can help me avoid doing this?

Example of generated code

private List<Object> list;
public Object getList(){ return list; }

What I would like instead:

private List<Object> list;
public Object getList(){
    if (list == null) {
        return new ArrayList();
    }
    return list;
}
Whittier answered 22/7, 2016 at 8:48 Comment(3)
Why don't you just initialize the list?Lyell
"if the list has not been initialized" I would regard that as a bug. If for some reason you want / need lazy initialization, you can take a look at the documentation - it's impossible to miss @Getter(lazy=true). Incidentally the required code is the same as for just initializing the list in the first place.Barbaresi
@JFMeier initializing the variable won't prevent from using x.setList(null) to happen. So the getList() is not guaranteed to be not null.Brahui
I
31

You can achieve this by declaring and initializing the fields. The initialization will be done when the enclosing object is initialized.

private List<Object> list = new ArrayList();

Lomboks @Getter annotation provides an attribute lazy which allows lazy initialization.

 @Getter(lazy=true) private final double[] cached = expensiveInitMethod();

Documentation

Intend answered 22/7, 2016 at 8:52 Comment(2)
"Lombok does not support initialize on read" Actually it does.Barbaresi
@zeroflagL Thanks, I never used this because it's not possible with '@Data' but the java way is.Intend
M
23

I had the same questions as of this one. Though, the above answers are useful in some ways, the exact solution is to use @Builder and @Singular annotations of Lombok API like below given code.

It worked superb for me.

@Builder
class MyClass{
    @Singular
    private List<Type> myList;
}

This will initialize myList with a non-null List object. Though, this questions is an old one. But, still posting this answer to help someone like me who will refer this question in future.

Margherita answered 2/10, 2017 at 14:41 Comment(2)
Cool! But doesn't this only work with the builder? The docs say that the list would be immutable.Albacore
Yeah but the collection is still null inside of the POJO.Overview
T
4

Newest versions of lombok do not generate a getter method if a getter method is provided with the same name and number of parameters.

With older versions of lombok, you can override the getter with anything you like by using AccessLevel.NONE on the field.

Note that merely initializing the field does not protect you from clients calling a constructor with nulls, or calling a setter with null (Still may be okay, depending on what you want).

E.g.

// only necessary for older versions of lombok
@Getter(AccessLevel.NONE)
private Map<String, String> params;

public Map<String, String> getParams() {
    return (params == null) ? new HashMap<>() : params;
}
Thyrsus answered 27/2, 2017 at 2:28 Comment(5)
Readers should be aware that Collections.emptyMap() returns an immutable map (one is unable to add entries when getting a map via this call).Oberstone
I replaced with new HashMap()Thyrsus
Please be aware that returning new HashMap() may cause data loss. Consider following code: ``` p = yourObject.getParams(); p.put("k","v"); actualParams = yourObject.getParams(); assert actualParams.size() == 1 //will fail here because params field remains unmodified ```Phosphorism
Nowadays, you don't even need to mark the field with @Getter(AccessLevel.NONE). If you would define your own getter method, Lombok will not create one: "No method is generated if any method already exists with the same name (case insensitive) and same parameter count." (see documentation).Leyes
@Jacob: thanks, I changed. Feel free to further update my answer if you want to.Thyrsus
I
0

Like mentioned newer versions of Lombok won't overwrite your own implementation.. But instead of writing the getter, write the setter!

By using the setter there is never a chance to have null in the variable! (except for reflection stuff...)

In my examples i have a list of Members...

public void setMembers(List<Member> members) {
    this.members = members != null ? members : new ArrayList(10);
}

Note: If you work with frameworks like Hibernate and Jpa and use the getter variant this can cause your lists to be set to null by the framework when loading objects from the DB, the getter will give you a empty list, but code in the object can still get a NPE.

Also i want to correct some other answers:

If you do the getter variant, do not use the ternary operator!:

return (members == null) ? new ArrayList<>() : members;

why? Because you never set the new ArrayList to the object var! This can generate bugs if someone wants to manipulate the list! Do this instead:

if (members == null) {
    members = new ArrayList<>();
}
return members;
Ingeborgingelbert answered 13/3 at 15:44 Comment(0)
G
-1

An old question, but this plugin does what you want:

https://github.com/dmak/jaxb-xew-plugin

Using this plugin generated the getter as:

public List<BaseVariableType> getVariables() {
    if (variables == null) {
        variables = new ArrayList<BaseVariableType>();
    }
    return variables;
}
Genip answered 24/8, 2020 at 19:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.