注意 Lombok equals 方法的陷阱

2024-06-20 13:38:07 浏览数 (2)

版本

  • JDK 8
  • Lombok 1.18.12

问题

  • 今天一位网友在群里问到,Lombok @Data equals 方法对比两个对象,两个对象的值不相等,但结果为 True,下面我们来看看具体的代码:
代码语言:Java复制
package test;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode
class Vehicle {
    private int id;
    private String name;
}

@Data
class Bicycle extends Vehicle {
    private String run;
}

public class LombokTest {
    public static void main(String[] args) {
        Bicycle bicycle1 = new Bicycle();
        bicycle1.setId(1);
        bicycle1.setName("捷安特");
        bicycle1.setRun("run");

        Bicycle bicycle2 = new Bicycle();
        bicycle2.setId(1);
        bicycle2.setName("捷安特1");
        bicycle2.setRun("run");

        boolean equals = bicycle1.equals(bicycle2);
        System.out.println(equals);  // 打印 true
    }
}
  • 仔细看一下相信机智的朋友们就已经知道原因了,Lombok equals 方法默认不会调用父类的 equals 方法,而 name 字段属于父类字段,所以比较结果为 True
  • 我们看一下 Lombok 生成的 equals 方法:
代码语言:Java复制
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Bicycle)) {
            return false;
        } else {
            Bicycle other = (Bicycle)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                // 仅比较子类字段的值
                Object this$run = this.getRun();
                Object other$run = other.getRun();
                if (this$run == null) {
                    if (other$run != null) {
                        return false;
                    }
                } else if (!this$run.equals(other$run)) {
                    return false;
                }

                return true;
            }
        }
    }
  • 如果我们需要同时比较父类字段和子类字段如何实现呢?其实很简单,添加注解 @EqualsAndHashCode(callSuper = true) 表示调用 equals & hashCode 方法时同时调用父类方法。
代码语言:Java复制
@EqualsAndHashCode(callSuper = true)
@Data
class Bicycle extends Vehicle {
    private String run;
}

// 再次执行源代码结果为 False
  • 添加注解 @EqualsAndHashCode(callSuper = true) 生成的 equals 方法:
代码语言:Java复制
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Bicycle)) {
            return false;
        } else {
            Bicycle other = (Bicycle)o;
            if (!other.canEqual(this)) {
                return false;
            // 调用父类 equals 方法
            } else if (!super.equals(o)) {
                return false;
            } else {
                Object this$run = this.getRun();
                Object other$run = other.getRun();
                if (this$run == null) {
                    if (other$run != null) {
                        return false;
                    }
                } else if (!this$run.equals(other$run)) {
                    return false;
                }

                return true;
            }
        }
    }

个人简介

0 人点赞