Java的Object类的clone和equals

Object
介绍:

Object类是Java里面所有类的父类,任何类都默认继承Object类。由于全部默认继承,所以extends Object省略了。

注意:Object类中的getClass(),wait(),notify(),notifyAll()等方法被定义为final类型,因此不能吧被继承去重写。

clone()
概述:

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里将参数改变,这是就需要在类中复写clone方法(实现深复制)。

原码:

protected native Object clone() throws CloneNotSupportedException;

clonecopy 的区别
假设 现在有一个Employee对象,Employee tobby =new Employee(“CMTobby”,5000)
    通常我们会有这样的赋值Employee cindyelf=tobby,这个时候只是简单了copy了一下reference,cindyelf和tobby都指向内存中同一个object,
    这样cindyelf或者tobby的一个操作都可能影响到对方。打个比方,如果我们通过cindyelf.raiseSalary()方法改变了salary域的值,那么tobby通过
    getSalary()方法得到的就是修改之后的salary域的值,显然这不是我们愿意看到的。我们希望得到tobby的一个精确拷贝,同时两者互不影响,这时候
    我们就可以使用Clone来满足我们的需求。Employee cindy=tobby.clone(),这时会生成一个新的Employee对象,并且和tobby具有相同的属性值和方法。
Shallow CloneDeep Clone
Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。
    以Employee为例,它里面有一个域hireDay不是基本数据类型的变量,而是一个reference变量,经过Clone之后就会产生一个新的Date型的reference,
    它和原始对象中对应的域指向同一个Date对象,这样克隆类就和原始类共享了一部分信息,如果修改这个克隆类的Data对象的值,则原先的Data对象的值也会改变,这样是不合理的,所以我们可以先在Data里面重写克隆,然后在Employee里面再重写一次克隆,这样就解决了只克隆一部分的问题了
// 克隆方法重写 deep clone【浅克隆套浅克隆】
package com.bigdata.practice0923;

public class Emp implements Cloneable {
	String empNo;
	private String eName;
    ......
    /**
     * 浅克隆
     */
	@Override
	protected Emp clone() throws CloneNotSupportedException{
		return (Emp)super.clone();
	}
	@Override
	public String toString() {
		return "Emp [empNo=" + empNo + ", eName=" + eName +"]";
	}
}


package com.bigdata.practice0923;

public class Dept implements Cloneable{
	private String deptNo;
	private String dName;
	private String loc;
	// 属性是一个类对象  如果多这个类不进行继承重写克隆这一系列操作的话 克隆的对象如果修改会改变该对象的值 算不上真正的克隆了就 
	Emp emp;
	......
     /**
      * depp克隆
      */
	@Override
	protected Dept clone() throws CloneNotSupportedException {
		Dept d = (Dept)super.clone();
		d.emp = emp.clone();
		return d;
	}
	
	@Override
	public boolean equals(Object obj) {
        if (obj instanceof Dept) {
			Dept d = (Dept) obj;
			if (this.deptNo.equals(d.deptNo) && this.dName.equals(d.dName) && this.loc.equals(d.loc)) {
				return true;
			}else {
				return false;                
			}
		}
        return false;
    }

	@Override
	public String toString() {
		return "Dept [deptNo=" + deptNo + ", dName=" + dName + ", loc=" + loc + ", emp=" + emp + "]";
	}
}
clone 方法的保护机制

在Object中Clone()是被声明为protected的,这样做是有一定的道理的,以Employee类为例,通过声明为protected,就可以保证只有Employee类里面【继承关系】才能“克隆”Employee对象

clone 方法的使用

​ 什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,基本数据类型还是reference variable【引用数据类型】

​ 调用Clone()方法的对象所属的类(Class)必须implements Clonable接口,否则在调用Clone方法的时候会抛出CloneNotSupportedException

String类已经重写了clone方法,可以直接使用
toString()
原码:
public String toString() {

   return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
用处:返回一个字符串【类名 、@ 和 该对象的哈希码的无符号十六进制 表示组成】
注意:用的较多,一般子类都有覆盖
例子:
package com.bigdata.practice0922;

public class ObjectTest {

	public static void main(String[] args) {
		Object o1 = new Object();
		System.out.println(o1.toString());
	}
}
>>>>>:
java.lang.Object@3b192d32
重写:

一般子类都会去按照自己的需求重写该类,String类已经重写好了!

equals()
原码:
public boolean equals(Object obj) {
  return (this == obj);
}
用处:

Object中直接判断 thisobj 本身的值是否相等。【调用equals的对象和equals的形参obj所引用的对象是否是同一对象】

注意:

同一对象是指内存中的同一块存储单元,相同返回true,否则返回false

使用:

如果要不同内存相同内容时需要返回 true, 则需要我们重写父类的 equals() 方法,String已经重写了,所以比较的是内容。

【Object的equals本质上和双等相同】

例子:
package com.bigdata.practice0922;

public class ObjectTest {
	public static void main(String[] args) {
		String str = "中国";
		String str1 = str;
		System.out.println(str.equals(str1));
	}
}
>>>>>>>:
true
双等和equals的比较:
  • Object的equals本质与双等相同
  • 双等比较的是栈里面存的值是否相同
  • String的equals重写Object的,比较的是字符串的内容【堆里存的值】是否相同【字符数组方式实现的】
  • String已经重写了equals方法
package com.bigdata.practice0923;

public class EqualsTest {
	public static void main(String[] args) {
		// Object的equals本质与双等相同  
		// String已经重写了 equals	相同的内容其实在堆里面只有一份 通过不同方式(hash 地址)去存储操作的  
		String str = "中国";
		String str1 = "中国";
		
		String str2 = new String("中国");
		String str3 = new String("中国");
		
//		双等比较的是栈里面存的值是否相同   
//		【直接给值 常量池hash与数组首地址操作  new是堆里面hash与数组首地址操作的】
//		【String中的equals是通过字符数组一一比较值的方式去判断是否相同的】
		System.out.print("双等内容相同直接初始化的字符串:");
		System.out.println(str == str1);
		System.out.print("双等内容相同一个直接给值一个new出来的字符串:");
		System.out.println(str == str2);
		System.out.print("双等内容相同new出来的字符串:");
		System.out.println(str2 == str3);
//		String的equals重写Object的,比较的是字符串的内容是否相同
		System.out.println("equals:");
		System.out.println(str.equals(str1));
		System.out.println(str.equals(str2));
		System.out.println(str2.equals(str3));
	}
}
  • 重写equals:
	/**
	 * 重写equals方法
	 */
	@Override
	public boolean equals(Object obj) {
        if (obj instanceof Dept) {
			Dept d = (Dept) obj;
			if (this.deptNo.equals(d.deptNo) && this.dName.equals(d.dName) && this.loc.equals(d.loc)) {
				return true;
			}else {
				return false;
			}
		}
        return false;
    }

package com.bigdata.practice0923;

public class EqualsTest2 {

	public static void main(String[] args) {
		Dept d1 = new Dept("N001", "开发部", "兰州");
		Dept d2 = new Dept("N001", "开发部", "兰州");
		
		System.out.println(d1 == d2); //  false
//		System.out.println(d1.equals(d2)); 	// false  这个equals是父类Object的 本质和==相同
		// 重写equals 之后
		System.out.println(d1.equals(d2)); // true
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值