你了解过clone()和new()吗

clone和new的比较

克隆

new clone
新的对象占据新的内存地址 新的对象占据新的内存地址
新的对象初始状态下没有属性值 新的对象初始状态下存在与被克隆对象的属性值相同
在使用new方法创建对象时,需要调用构造方法,效率相对低 不需要调用构造方法,效率相对高

深拷贝与浅拷贝

深拷贝 浅拷贝
新对象与旧对象属性值相同,但是逻辑地址不同 新对象与旧对象属性值相同,逻辑地址也相同

⚪浅拷贝实际上clone的不是一个对象,而是一个引用,但是他们都指向同一个对象地址,因此他们的逻辑地址是相同的。如下图所示。
在这里插入图片描述

⚪深拷贝实际上clone是一个对象,他们指向不同的对象地址,因此他们的逻辑地址是不相同的。如下图所示。

在这里插入图片描述

⚪显然两种拷贝出来的结果属性值都是与被拷贝对象相同的。但是我们也很容易发现,如果用的是浅拷贝,object的值发生了改变,p1和p2的值都会随之改变。但是如果时深拷贝,p1指向的对象属性值发生改变时,不会影响被克隆出来的p2的值。

深浅拷贝代码实现

思路

1.实现cloneable方法,并且重写clone方法。
2.私有属性name,并生成get set方法
3.重写tostring方法,方便测试时的观察

package clone;

public class people implements Cloneable{

	private String name;
	
	public people(String name) {
		super();
		this.name = name;
	}

	@Override
	public String toString() {
		return name;//重写了toString方法,方便测试时观察
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		System.out.println("对象已被克隆");
		return super.clone();
	}
}




1.创建了一个深拷贝对象like和浅拷贝对象clone
2.使用object.hashcode输出他们的逻辑地址。
3.使用object.toString输出他们的属性值。
4.详看代码中的注解

package clone;
/**
 * 在对象属性很多时,使用clone比使用new效率高。因为new还需要去调用构造方法,而且new之后的对象属性值全是空的,使用clone方法
 * clone过去的属性值与被克隆的对象一样。
 * @author dell
 *
 */
public class Test {

	public static void main(String[] args) throws CloneNotSupportedException {
	    
		people p = new people("小明");
		people like = p; //浅拷贝对象like
		Object clone = p.clone(); //深拷贝对象clone
		/**
		 * 深拷贝(对象类实现了cloneable方法,并重写clone方法。测试类调用方法并抛出CloneNotSupportedException异常)
		 */
		System.out.println(clone.hashCode()+"   "+p.hashCode());
		System.out.println(p.toString()+"  "+clone.toString());
		
		System.out.println("--------------------------------");
		/**
		 * 浅拷贝(like和p为同一个逻辑地址,实际上就是把值拷贝了一份)
		 */
		System.out.println(like.hashCode()+"   "+p.hashCode());
		System.out.println(like.toString()+"   "+p.toString());
		
	}
	
}




测试结果:
在这里插入图片描述

看看源码

在这里插入图片描述
这是克隆的源码,它抛出一个“克隆不支持异常”。
使用native修饰,意是底层不是用java语言编写的,使用native修饰符去调用本地dll文件中的内容。
代码使用protected修饰,说明使用该方法,必须继承Object(extends Object),之后重写该方法。但是在代码中不写extends Object也没事,因为万物皆对象,所有类都直接或者间接地继承了Object类

发布了5 篇原创文章 · 获赞 1 · 访问量 3811

猜你喜欢

转载自blog.csdn.net/weixin_43379487/article/details/105735709
今日推荐