记lombok@Data和@Builder一起用无法添加无参构造方法的坑

简介: 记lombok@Data和@Builder一起用无法添加无参构造方法的坑

一、结论先行

手写默认构造方法,然后加上 @Tolerate 注解即可。


@Builder

@Data

public class Dog {

   private String name;

   private Integer age;

   private String nickName;

   private String test;

   @Tolerate

  public Dog() {}

}

二、详情(感兴趣继续看)

今天和小伙伴讨论一个mybatis-plus的一个诡异问题,最后定位到原因竟然是lombok@Data和@Builder一起用无法添加无参构造方法引起的,非常隐蔽。


很多框架都是同反射等调用无参数构造方法来创建实例的,需要注意。


单独使用@Data注解,编译后的类文件会生成无参数构造方法(这并不是@Data提供的特性,而是Java自带的特性)。


 // IntelliJ API Decompiler stub source generated from a class file

 // Implementation of methods is not available

package com.chujianyun.util;

public class Dog {

   private java.lang.String name;

   private java.lang.Integer age;

   private java.lang.String nickName;

   private java.lang.String test;

   public Dog() { /* compiled code */ }

   public java.lang.String getName() { /* compiled code */ }

   public java.lang.Integer getAge() { /* compiled code */ }

   public java.lang.String getNickName() { /* compiled code */ }

   public java.lang.String getTest() { /* compiled code */ }

   public void setName(java.lang.String name) { /* compiled code */ }

   public void setAge(java.lang.Integer age) { /* compiled code */ }

   public void setNickName(java.lang.String nickName) { /* compiled code */ }

   public void setTest(java.lang.String test) { /* compiled code */ }

   public boolean equals(java.lang.Object o) { /* compiled code */ }

   protected boolean canEqual(java.lang.Object other) { /* compiled code */ }

   public int hashCode() { /* compiled code */ }

   public java.lang.String toString() { /* compiled code */ }

}

单独使用@Builder注解,发现生成了全属性的构造方法。


package com.chujianyun.util;

public class Dog {

   private java.lang.String name;

   private java.lang.Integer age;

   private java.lang.String nickName;

   private java.lang.String test;

   Dog(java.lang.String name, java.lang.Integer age, java.lang.String nickName, java.lang.String test) { /* compiled code */ }

   public static com.chujianyun.util.Dog.DogBuilder builder() { /* compiled code */ }

   public static class DogBuilder {

       private java.lang.String name;

       private java.lang.Integer age;

       private java.lang.String nickName;

       private java.lang.String test;

       DogBuilder() { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder name(java.lang.String name) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder age(java.lang.Integer age) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder nickName(java.lang.String nickName) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder test(java.lang.String test) { /* compiled code */ }

       public com.chujianyun.util.Dog build() { /* compiled code */ }

       public java.lang.String toString() { /* compiled code */ }

   }

}

@Data和@Builder一起用


@Data

@Builder

public class Dog {

   private String name;

   private Integer age;

   private String nickName;

   private String test;

}

效果


 // IntelliJ API Decompiler stub source generated from a class file

 // Implementation of methods is not available

package com.chujianyun.util;

public class Dog {

   private java.lang.String name;

   private java.lang.Integer age;

   private java.lang.String nickName;

   private java.lang.String test;

   Dog(java.lang.String name, java.lang.Integer age, java.lang.String nickName, java.lang.String test) { /* compiled code */ }

   public static com.chujianyun.util.Dog.DogBuilder builder() { /* compiled code */ }

   public java.lang.String getName() { /* compiled code */ }

   public java.lang.Integer getAge() { /* compiled code */ }

   public java.lang.String getNickName() { /* compiled code */ }

   public java.lang.String getTest() { /* compiled code */ }

   public void setName(java.lang.String name) { /* compiled code */ }

   public void setAge(java.lang.Integer age) { /* compiled code */ }

   public void setNickName(java.lang.String nickName) { /* compiled code */ }

   public void setTest(java.lang.String test) { /* compiled code */ }

   public boolean equals(java.lang.Object o) { /* compiled code */ }

   protected boolean canEqual(java.lang.Object other) { /* compiled code */ }

   public int hashCode() { /* compiled code */ }

   public java.lang.String toString() { /* compiled code */ }

   public static class DogBuilder {

       private java.lang.String name;

       private java.lang.Integer age;

       private java.lang.String nickName;

       private java.lang.String test;

       DogBuilder() { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder name(java.lang.String name) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder age(java.lang.Integer age) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder nickName(java.lang.String nickName) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder test(java.lang.String test) { /* compiled code */ }

       public com.chujianyun.util.Dog build() { /* compiled code */ }

       public java.lang.String toString() { /* compiled code */ }

   }

}

我们发现外层的Dog类没有了默认的构造方法。


如果手动添加无参数构造方法或者用@NoArgsConstructor注解都会报错!


@Builder

@Data

@NoArgsConstructor

public class Dog {

   private String name;

   private Integer age;

   private String nickName;

   private String test;

}



正确写法如下:


@Builder

@Data

public class Dog {

   private String name;

   private Integer age;

   private String nickName;

   private String test;

   @Tolerate

  public Dog() {}

}

解释如下




添加函数或者构造方法,让lombok假装它不存在(不感知)。


效果如下:


package com.chujianyun.util;

public class Dog {

   private java.lang.String name;

   private java.lang.Integer age;

   private java.lang.String nickName;

   private java.lang.String test;

   Dog() { /* compiled code */ }

   Dog(java.lang.String name, java.lang.Integer age, java.lang.String nickName, java.lang.String test) { /* compiled code */ }

   public static com.chujianyun.util.Dog.DogBuilder builder() { /* compiled code */ }

   public java.lang.String getName() { /* compiled code */ }

   public java.lang.Integer getAge() { /* compiled code */ }

   public java.lang.String getNickName() { /* compiled code */ }

   public java.lang.String getTest() { /* compiled code */ }

   public void setName(java.lang.String name) { /* compiled code */ }

   public void setAge(java.lang.Integer age) { /* compiled code */ }

   public void setNickName(java.lang.String nickName) { /* compiled code */ }

   public void setTest(java.lang.String test) { /* compiled code */ }

   public boolean equals(java.lang.Object o) { /* compiled code */ }

   protected boolean canEqual(java.lang.Object other) { /* compiled code */ }

   public int hashCode() { /* compiled code */ }

   public java.lang.String toString() { /* compiled code */ }

   public static class DogBuilder {

       private java.lang.String name;

       private java.lang.Integer age;

       private java.lang.String nickName;

       private java.lang.String test;

       DogBuilder() { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder name(java.lang.String name) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder age(java.lang.Integer age) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder nickName(java.lang.String nickName) { /* compiled code */ }

       public com.chujianyun.util.Dog.DogBuilder test(java.lang.String test) { /* compiled code */ }

       public com.chujianyun.util.Dog build() { /* compiled code */ }

       public java.lang.String toString() { /* compiled code */ }

   }

————————————————

版权声明:本文为CSDN博主「明明如月学长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/w605283073/article/details/89221853

相关文章
|
2月前
|
Java 程序员 数据库连接
Java执行顺序大揭秘:静态块、非静态块和构造方法谁先谁后?
本文详细介绍了Java中的初始化块,包括静态初始化块和非静态初始化块的概念、执行顺序和实际应用场景。通过具体示例,帮助读者理解这两种初始化块的区别和使用场景,让面试官对你刮目相看。
42 0
Java执行顺序大揭秘:静态块、非静态块和构造方法谁先谁后?
|
2月前
|
Java
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
|
4月前
|
Java
lombok的使用
本文介绍了Lombok库的基本使用方法和常用注解,通过示例代码展示了如何使用Lombok简化Java对象的创建、属性访问、日志记录等编码工作,使代码更加简洁。
lombok的使用
|
3月前
|
设计模式 Java 测试技术
Java零基础-构造方法详解
【10月更文挑战第5天】Java零基础教学篇,手把手实践教学!
53 1
|
3月前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
110 1
|
4月前
|
Java API
java调用构造方法
java调用构造方法
54 3
|
4月前
|
IDE Java 编译器
lombok编译遇到“找不到符号的问题”
【9月更文挑战第18天】当使用 Lombok 遇到 “找不到符号” 的问题时,可能是由于 Lombok 未正确安装、编译器不支持、IDE 配置不当或项目构建工具配置错误。解决方法包括确认 Lombok 安装、编译器支持,配置 IDE 和检查构建工具配置。通过这些步骤通常可解决问题,若问题仍存在,建议检查项目配置和依赖,或查看日志获取更多信息。
2203 2
|
5月前
|
Java
【Java基础面试十九】、构造方法能不能重写?
这篇文章指出Java中的构造方法不能被重写,因为构造方法必须与类名相同,而重写要求子类方法与父类方法同名,允许构造方法重写将违背这一规则。
【Java基础面试十九】、构造方法能不能重写?
|
3月前
|
Java
java构造方法的两种传值调用对实参的影响
java构造方法的两种传值调用对实参的影响
33 0
|
3月前
|
Java 程序员 编译器
【Java】继承、super、final、子类构造方法
【Java】继承、super、final、子类构造方法
57 0