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类