Lombok @ Builder.Default强制默认值可选值为null

时间:2018-03-29 23:50:22

标签: java-8 jackson optional lombok

在我的代码中,我有一个类似于以下

的类
public enum Test {
    VALUE1,
    VALUE2
}

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class MyClass {
  @JsonProperty(name = "test")
  private Optional<Test> test = Optional.empty();

}

这样可以正常工作,但它会出现以下错误:

  

警告:@Builder将完全忽略初始化表达式。

太棒了,让我添加@Builder.Default ...

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class MyClass {
  @Builder.Default
  @JsonProperty(name = "test", required = true)
  private Optional<Test> test = Optional.empty();  
}

这可以修复错误,但现在test值在不存在Optional.empty时会被强制为空。我想保留Optional模式,让对象的用户决定他们如何处理Optional,而不是Lombok或Jackson。

有没有办法让这项工作正常,默认值仍为Optional.empty()?如果没有,有没有办法可以忽略这个警告,因为它无法修复?

修改

想象一下,我们将一个有效负载传递给一个空的端点(因为我们想测试对象中 only 值的可选项)

POST /my/end/point

,有效负载为{}

然后我们使用杰克逊来取回物品

MyClass result = mapper.readValue(payload, MyClass.class);

当我们查看生成的对象时,我们会发现使用MyClass.testnullOptional.empty()而不是@Builder.Default。否则,我们会收到上面的警告,但默认值已正确指定为Optional.empty()

2 个答案:

答案 0 :(得分:1)

存在代码风格问题。让Lombok为可选字段生成getter / setter / constructor / builder会导致:

public MyClass(Optional<Test> test) {
    this.test = test;
}

public Optional<Test> getTest() {
    return test;
}

public void setTest(Optional<Test> test) {
    this.test = test;
}

// ... imagine Builder here ...

getter没问题,但是构造函数,setter和Builder变得非常不方便使用。您必须使用Test上的一个静态方法包装Optional,如下所示:

// If value is known
myClass.setTest(Optional.of(Test.VALUE1));

// If initializing with a variable which maybe null
myClass.setTest(Optional.ofNullable(anotherTest));

很难看。还有更好的方法。
我假设你只想在getter上使用Optional作为返回类型,所以提供你自己的getter实现,迫使Lombok不生成它自己的。

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class MyClass {

    @JsonProperty(name = "test", required = true)
    private Test test;

    public Optional<Test> getTest() {
        return Optional.ofNullable(test);
    }
}

智慧之源:JAVAFX: Location is not set error

答案 1 :(得分:0)

由于你有一个构建器,我建议切换到@Value,使你的类不可变。如果要在构建对象后进行进一步更改,可以使用toBuilder选项。

至于Optional setters“丑陋”的论点,我认为他们错过了Optional的观点。如果您从整体上使用Optionals,那么正在进行设置的生产代码将具有可选项。要求它用于setter或builder参数意味着调用者必须确定参数是否为null。这是件好事!调用者必须考虑并处理可能的空值,可能是重构,以便上面的层也必须提供可选的,等等。

在实践中,可空值通常来自像杰克逊这样的反序列化框架,它可以为你做包装。这意味着你实际上不必经常处理“丑陋”。

永远不要跳过可以删除代码中的错误的内容,因为有人说它很难看。错误较少的代码很漂亮。