Java.lang.Illegalaccessexception 或 java.lang.NoSuchMethodError

2020-09-16 14:31:56 浏览数 (1)

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

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

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

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

代码语言:javascript复制
   // 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注解,发现生成了全属性的构造方法。

代码语言:javascript复制
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一起用

代码语言:javascript复制
@Data@Builderpublic class Dog {     private String name;     private Integer age;     private String nickName;     private String test; }

效果

代码语言:javascript复制
   // 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注解都会报错!

代码语言:javascript复制
@Builder@Data@NoArgsConstructorpublic class Dog {     private String name;     private Integer age;     private String nickName;     private String test; }

正确写法如下:

代码语言:javascript复制
@Builder@Datapublic class Dog {     private String name;     private Integer age;     private String nickName;     private String test;     @Tolerate    Dog() {}}

解释如下

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

效果如下:

代码语言:javascript复制
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 */ }    }}

完美。

0 人点赞