java 克隆,使用@Data注解与不使用时的不同

今天学习了下对象的克隆,其中克隆有以下三条约定

  1. 对于所有对象来说,x.clone() !=x 应当返回 true,因为克隆对象与原对象不是同一个对象;
  2. 对于所有对象来说,x.clone().getClass() == x.getClass() 应当返回 true,因为克隆对象与原对象的类型是一样的;
  3. 对于所有对象来说,x.clone().equals(x) 应当返回 true,因为使用 equals 比较时,它们的值都是相同的。

而对于第3条中的描述:“x.clone().equals(x) 应当返回 true”表示了疑问,因为我们知道:


 1. ==:对于基础类型数据来说,比较的是值,对于引用数据来说,比较
 的是地址那一串字符串是否相等。
 2. equals:看源码得知,Object的equals,也只是用==比较了两个对
 象,所以根本就没啥意义,而String重写了equals方法,对引用所指
 向的值进行比较

Object:
 public boolean equals(Object obj) {
        //相等于还是只比较了引用字符串是否相等
        return (this == obj);
    }

String:
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

正是由于objec的equals方法比较的引用,所以x.clone().equals(x) 返回的应该是false,怎么会返回true呢。

随后我写方法进行试验,分别使用了@Data和不使用@Data两种方式进行了测试(也是无意间发现的,不要问为啥专门测了这两种)

@Data
public class Clon1 implements Cloneable {
    private String name;
    private  String age;

	public Clon1(String name, String age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

	public static void main(String[] args) throws Exception {
        Clon1 clon1 = new Clon1("clon1","20");
        Clon1 clon2 = (Clon1) clon1.clone();
        System.out.println(clon1==clon2);//false
        System.out.println(clon1.equals(clon2));//true
    }
}


/**************不使用@Data↓↓↓↓********************************/
public class Clon1 implements Cloneable {
    private String name;
    private  String age;

	public Clon1(String name, String age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

	public static void main(String[] args) throws Exception {
        Clon1 clon1 = new Clon1("clon1","20");
        Clon1 clon2 = (Clon1) clon1.clone();
        System.out.println(clon1==clon2);//false
        System.out.println(clon1.equals(clon2));//false
    }
}

最后发现,使用了@Data注解的类,经过编译反编译,发现它不仅提供了set、get方法,还重写了equals方法,而equals方法,则对对象中的属性值进行比较,全部相等则返回为true

使用@Data注解时重写的equals方法
	@Override
	public boolean equals(Object o) {
		if (o == this) return true;
		if (!(o instanceof Clon1)) return false;
		Clon1 other = (Clon1)o;
		if (!other.canEqual(this)) return false;
		Object this$name = getName();
		Object other$name = other.getName();
		if (this$name == null ? other$name != null : !this$name.equals(other$name))
			return false;
		Object this$age = getAge();
		Object other$age = other.getAge();
		return this$age == null ? other$age == null : this$age.equals(other$age);
	}
	
	protected boolean canEqual(Object other) { return other instanceof Clon1; }

至此,使用@Data注解与不使用注解时,为啥equals结果会是不同的结果,也随之解开了:正是因为 @Data注解重写了equls方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值