花门楼前见秋草,岂能贫贱相看老。

注解

@EqualsAndHashCode(callSuper = true)

当标注@Data的类继承其它( 非Object ) 时IEAD提示

生成 equals/hashCode 实现,但即使此类未扩展 java.lang.Object,也不调用超类。如果这是有意为之,请在您的类型中添加 ‘(callSuper=false)’

父类

@Data
public abstract class AbstractAuditBase {

    private Instant createdTime;

    private Instant updatedTime;

    private String createdBy;

    private String updatedBy;
}

子类

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Balance extends AbstractAuditBase implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;
    
    private String name;
    
    private BigDecimal balance;

    public Balance( String name, BigDecimal balance) {
        this.name = name;
        this.balance = balance;
    }
    public Balance(Integer id, BigDecimal balance) {
        this.id = id;
        this.balance = balance;
    }
}

测试

    @Test
    public void test1() {
        Balance balance1 = new Balance(1, BigDecimal.ONE);
        Balance balance2 = new Balance(1, BigDecimal.TEN);
        Balance balance3 = new Balance(1, BigDecimal.ONE);

        System.out.printf("balance1: %s\t balance2: %s\t equals:%s\n", balance1, balance2, balance1.equals(balance2));
        System.out.printf("balance1: %s\t balance3: %s\t equals:%s\n", balance1, balance3, balance1.equals(balance3));

        balance1.setCreatedBy("1");
        balance3.setCreatedBy("3");
        System.out.printf("balance1: %s\t balance3: %s\t equals:%s\n", balance1, balance3, balance1.equals(balance3));
    }

输出

balance1: Balance(id=1, name=null, balance=1)	 balance2: Balance(id=1, name=null, balance=10)	 equals:false
balance1: Balance(id=1, name=null, balance=1)	 balance3: Balance(id=1, name=null, balance=1)	 equals:true
balance1: Balance(id=1, name=null, balance=1)	 balance3: Balance(id=1, name=null, balance=1)	 equals:true

此时 Balance 类生成的字节码中equals方法,并没有调用父类的字段进行比较。

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Balance)) {
            return false;
        } else {
            Balance other = (Balance)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$id = this.getId();
                    Object other$id = other.getId();
                    if (this$id == null) {
                        if (other$id == null) {
                            break label47;
                        }
                    } else if (this$id.equals(other$id)) {
                        break label47;
                    }

                    return false;
                }
                ...
            }
        }
    }

根据 IDEA 提示,在 Balance 上添加注解

image-20230506110159437

image-20230506111141385

运行测试

balance1: Balance(id=1, name=null, balance=1)	 balance2: Balance(id=1, name=null, balance=10)	 equals:false
balance1: Balance(id=1, name=null, balance=1)	 balance3: Balance(id=1, name=null, balance=1)	 equals:true
balance1: Balance(id=1, name=null, balance=1)	 balance3: Balance(id=1, name=null, balance=1)	 equals:false

Balance 生成的字节码 equal 方法


    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Balance)) {
            return false;
        } else {
            Balance other = (Balance)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (!super.equals(o)) { //调用了父类的equal方法
                return false;
            } else {
                ....
        }
    }

总结

@EqualsAndHashCode 基于相关字段为所有对象继承的equals和hashCode方法生成实现。

@Data注解包含了该注解,并且默认不调用父类equals

image-20230506111519137

boolean callSuper() default false;

因此在使用@Data注解时需要注意被标注的类是否继承了非 Object 类,子类的equals是否需要调用父类 equals()

  • 是:@EqualsAndHashCode(callSuper = true)
  • 否:@EqualsAndHashCode(callSuper = false)

同理 @ToString 也可以根据需要是否调用父类方法 @ToString(callSuper = true)

balance1: Balance(super=AbstractAuditBase(createdTime=null, updatedTime=null, createdBy=null, updatedBy=null), id=1, name=null, balance=1)	

Getter、Setter方法生成

使用 @Data,@Getter,@Setter时需要注意布尔字段。


@Data
public class User {
    private String id;
    private boolean success;
    private boolean isOk;
    private Boolean failure;
}

字节码中生成的方法。

public class User {
    private String id;
    private boolean success;
    private boolean isOk;
    private Boolean failure;

    public String getId() {
        return this.id;
    }

    public boolean isSuccess() {
        return this.success;
    }

    public boolean isOk() {
        return this.isOk;
    }

    public Boolean getFailure() {
        return this.failure;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public void setOk(boolean isOk) {
        this.isOk = isOk;
    }

    public void setFailure(Boolean failure) {
        this.failure = failure;
    }

    public boolean equals(Object o) {
			...
    }

    protected boolean canEqual(Object other) {
        return other instanceof User;
    }

    public int hashCode() {
			...
    }

    public String toString() {
        String var10000 = this.getId();
        return "User(id=" + var10000 + ", success=" + this.isSuccess() + ", isOk=" + this.isOk() + ", failure=" + this.getFailure() + ")";
    }

    public User() {
    }
}

总结

  • 对于布尔的基本类型 “get” 方法 为 “is”+“字段名称”;并且字段名前缀已包含 “is” 时,生成的方法中会自动简化。
  • 对于布尔包装类型,“get”方法不变。
  • 推荐:对于 JavaBean 的字段类型可一律采用包装类型(另一方面原因:包装类型默认值为 null,可以空值阻断)。

@Slf4j日志打印

对 ‘printStackTrace()’ 的调用可能应当替换为更可靠的日志

e.printStackTrace() 和 System.out.print() 一样是不会把信息输出到日志文件的。

解决措施:

使用 log.error(e.getMessage(),e); 将错误信息通过日志对象输出到日志文件。

版权声明:如无特别声明,本站收集的文章归  HuaJi66/Others  所有。 如有侵权,请联系删除。

联系邮箱: [email protected]

本文标题:《 Lombok使用注意事项 》

本文链接:/%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3/%E5%B7%A5%E5%85%B7/Lombok%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.html