简体   繁体   中英

Override lombok builder and change value type

I have the below class with Lombok @Builder where I override one builder method to convert the input string list into an enum list (field barList ):

(I still use the default method for the other field number )

import java.util.List;
import java.util.stream.Collectors;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder(toBuilder = true)
public class Foo {
    private List<BarEnum> barList;
    private int number;

    public static class FooBuilder {
        private List<BarEnum> barList;
       
        public FooBuilder barList(List<String> barStringList) {
            this.barList = barStringList.stream()
                                        .map(barString -> BarEnum.valueOf(barString))
                                        .collect(Collectors.toList());
            return this;
        }
    }
}

When compiling, I get this error on the line @Builder(toBuilder = true) above:

incompatible types: java.util.List<com.mypackage.BarEnum> cannot be converted to java.util.List<java.lang.String>

I couldn't find any answers where I can override the default builder method and change a value type. Is it possible to do this?

First we run delombok to get a better idea of what's happening, and then compile the output.

java -jar lombok.jar delombok -p Foo.java >Foo2.java
# Rename Foo2.java or make the `class Foo` declaration non-public
javac Foo2.java

gets us:

Foo2.java:63: error: incompatible types: List<BarEnum> cannot be converted to List<String>
        return new Foo.FooBuilder().barList(this.barList).number(this.number);
                             ^

And then the answer is clear: Lombok needs the barList(List<BarEnum>) variant of the builder barList method to exist. By writing it yourself, lombok doesn't generate its own version.

Lombok core developer speaking here: We don't, because it is quite difficult to ascertain if there is a signature clash. Thus, we notice a method with the same name as something we want to generate and with the same argument count, and we don't do any further analysis: That's a 'match' and means lombok doesn't generate this method anymore, assuming that you've taken over the responsibility for it. This is a fine, fine example: There cannot be a barList(List<BarEnum>) method in addition to your explicit barList(List<String>) method because you can't have 2 methods that differ solely in the generics parts of the arguments. (Try it - won't compile).

Thus, your approach here is fundamentally untenable. The fix is fairly easy - make that custom method something like:

public FooBuilder barStringList(List<String> barStringList) { .. }

ie give it another name. Now lombok will also generate barList(List<BarEnum>) and all will be well.

If you want the barlist(List<BarEnum>) variant to not exist, then don't, but you'll have to handwrite the toBuilder() part of it: At that point it is no longer possible for lombok to automatically know how to turn an instance into a pre-filled builder anymore, if you start just effectively removing the very methods that are needed as 'setters' to make that work.

DISCLAIMER: I'm a core lombok dev.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM