xxxDTO.buider().build()和new xxxDTO()的结果一样吗?

最近有一个逃逸的缺陷,从代码视角来看,主要是ExampleDTO.builder().build() 产生了与开发同学的预期不同。也就是四个BigDecimal类型的成员变量 bigDecimalField1-4是null而不是默认值 BigDecimal.ZERO。

代码语言:javascript代码运行次数:0运行复制
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Builder
@NoArgsConstructor
@AllArgsConstructor
class ExampleDTO {
 
private String stringField1;
 
private String stringField2;
 
  
private BigDecimal bigDecimalField1 = BigDecimal.ZERO;
 
private BigDecimal bigDecimalField2 = BigDecimal.ZERO;
 
private BigDecimal bigDecimalField3 = BigDecimal.ZERO;
}
public class Main {
 
public static void main(String[] args) {
 
ExampleDTO dto = ExampleDTO.builder().build();
System.out.println("stringField1: " + dto.stringField1);
System.out.println("stringField2: " + dto.stringField2);
System.out.println("bigDecimalField1: " + dto.bigDecimalField1);
 
System.out.println("bigDecimalField2: " + dto.bigDecimalField2);
System.out.println("bigDecimalField3: " + dto.bigDecimalField3);
 }
}

通过反编译的ExampleDTO.class的代码,可以看出来

ExampleDTO.builder().build()并不是等价于 new ExampleDTO(),而是以下的代码,

ExampleDTO exampleDTO=new ExampleDTO(null,null,null,null,null);

也就是 先调用new ExampleDTO()生成一个ExampleDTO的实例(此时bigDecimalField1-4都是默认值BigDecimal.ZERO),然后再通过带参构造方法将bigDecimalField1-4设置为null。

之前没有关注过这个细节,也算是个坑了。那么,感兴趣的读者也可以问问LLM如何让ExampleDTO.builder().build()等价于 new ExampleDTO() 呢?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-02,如有侵权请联系 cloudcommunity@tencent 删除bigdecimalbuildnull变量开发