Reputation: 67
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?
Upvotes: 2
Views: 3078
Reputation: 103783
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) { .. }
i.e. 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.
Upvotes: 4