java lombok遇到的问题

lombok 遇到的问题

@Data 注解的理解

@Data 注解其实是多个注解的集合,他完成了多个注解的功能,分别是:

  • @Getter
  • @Setter
  • @RequiredArgsConstructor
  • @ToString
  • @EqualsAndHashCode

有时候我们为了方便getter和setter方法的简单化,直接使用了@Data注解代替,很可能会产生意想不到的问题,特别是@EqualsAndHashCode,下面将对这个注解进行解释。

@EqualsAndHashCode 注解

定义一个Person类,使用@EqualsAndHashCode注解后,我们先看看会产生什么事情

  • 源码:
/**
 * @author xiaoming
 */
@EqualsAndHashCode
public class Person {

    private int sex;

    private int age;

    private String name;

    public static void main(String[] args) {
        System.out.println("run");
    }
}
  • 编译之后
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package lombok;

public class Person {
    private int sex;
    private int age;
    private String name;

    public Person() {
    }

    public static void main(String[] args) {
        System.out.println("run");
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Person)) {
            return false;
        } else {
            Person other = (Person)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.sex != other.sex) {
                return false;
            } else if (this.age != other.age) {
                return false;
            } else {
                Object this$name = this.name;
                Object other$name = other.name;
                if (this$name == null) {
                    if (other$name == null) {
                        return true;
                    }
                } else if (this$name.equals(other$name)) {
                    return true;
                }

                return false;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.sex;
        result = result * 59 + this.age;
        Object $name = this.name;
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }
}

可以看出,lombok在编译的时候重写了三个方法 :

  • hashCode
  • canEqual
  • equals

equals方法对各个参数多进行了校验,如果我们想使用引用进行equals方法比较的话,@Data就不能使用了。

这个时候可能会有同学思考了,如果涉及到继承,对子类添加注解,那子类会调用父类的equals 方法吗?

接着做实验,添加子类 Coder 继承 Person

  • 源码
/**
 * @author xiaoming
 */
@EqualsAndHashCode
public class Coder extends Person {

    private boolean loveJava;

    public static void main(String[] args) {
        System.out.println("run");
    }
}
  • 编译之后
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package lombok;

public class Coder extends Person {
    private boolean loveJava;

    public Coder() {
    }

    public static void main(String[] args) {
        System.out.println("run");
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Coder)) {
            return false;
        } else {
            Coder other = (Coder)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return this.loveJava == other.loveJava;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + (this.loveJava ? 79 : 97);
        return result;
    }
}

不能看出,equals 方法和 hashCode方法 只对子类成员进行了比较
那我们如何继承父类的equals方法呢?使用 callSuper = true

  • 源码
/**
 * @author xiaoming
 */
@EqualsAndHashCode(callSuper = true)
public class Coder extends Person {

    private boolean loveJava;

    public static void main(String[] args) {
        System.out.println("run");
    }
}
  • 编译后
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package lombok;

public class Coder extends Person {
    private boolean loveJava;

    public Coder() {
    }

    public static void main(String[] args) {
        System.out.println("run");
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Coder)) {
            return false;
        } else {
            Coder other = (Coder)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (!super.equals(o)) {
                return false;
            } else {
                return this.loveJava == other.loveJava;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = super.hashCode();
        result = result * 59 + (this.loveJava ? 79 : 97);
        return result;
    }
}

equals方法调用了super.equals方法和super.hashCode方法

查看注解的callSuper定义, 默认是false,当致为true的时候比较子类域成员之前会调用父类的equals和hashCode

	/**
	 * Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating for the fields in this class.
	 * <strong>default: false</strong>
	 * 
	 * @return Whether to call the superclass's {@code equals} implementation as part of the generated equals algorithm.
	 */
	boolean callSuper() default false;
	

lombok注解和用户自定义优先级

我们经常会使用@Data注解方便快捷,但是我们又想对toString方法自定义,那在同时使用的情况下会发生什么情况呢?

  • 源码
/**
 * @author xiaoming
 */
@EqualsAndHashCode
public class Person {

    private int sex;

    private int age;

    private String name;

    public static void main(String[] args) {
        System.out.println("run");
    }

    @Override
    public String toString() {
        return "user defined";
    }
}
  • 编译之后
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package lombok;

public class Person {
    private int sex;
    private int age;
    private String name;

    public Person() {
    }

    public static void main(String[] args) {
        System.out.println("run");
    }

    public String toString() {
        return "user defined";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Person)) {
            return false;
        } else {
            Person other = (Person)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.sex != other.sex) {
                return false;
            } else if (this.age != other.age) {
                return false;
            } else {
                Object this$name = this.name;
                Object other$name = other.name;
                if (this$name == null) {
                    if (other$name == null) {
                        return true;
                    }
                } else if (this$name.equals(other$name)) {
                    return true;
                }

                return false;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.sex;
        result = result * 59 + this.age;
        Object $name = this.name;
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }
}

通过代码不难看出,toString方法使用了我们自定义的
所以说优先级是用户自定义的高(其实大家思考一下也很容易想到)

总结

使用插件和注解会给我们带来很多的方便,也会让代码变得简洁,但是我们需要对这些注解真正的了解,不然出现问题的话会难以排除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值