java.lang.Cloneable接口
一个带空体的接口称为标记接口(marker interface)
既不包含常量也不包含方法,用来表示一个类拥有某些特定的属性
实现Cloneable接口的类标记为可克隆的
浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
Java 将内存空间分为堆和栈。基本类型直接在栈中存储数值,而引用类型是将引用放在栈中,实际存储的值是放在堆中,通过栈中的引用指向堆中存放的数据。
一个疑问:String作为引用类型,为什么它的浅复制也是直接复制的值呢?
String 类型很特殊,它是不可变类型,即一旦初始化后,就不可以改变。因为他为引用型,而且他指向的值为常量,克隆出来的对象改变他的值
实际上是改变了克隆出来对象String类型成员的指向,不会影响被克隆对象的。
解释:如果原来对象的一个string变量进行初始化的时候,指向的是一个字符串常量,该字符串常量会被放到常量池中,该string类型的引用将会指向该常量。进行克隆后,得到一个新的对象,如果该对象的string变量重新赋值,那么只会有这个string 引用变量指向一个新的内存区域,对原来对象中的string变量不会有影响。
public class Teacher implements Cloneable {
private String name;
private int id;
public Teacher(String name, int id) {
super();
this.name = name;
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneTest {
public static void main(String[] args) throws Exception {
Teacher t1 = new Teacher("张三", 1);
Teacher t3 = (Teacher) t1.clone();
System.out.println(t1.getName()+"\t"+t1.getId());
System.out.println(t3.getName()+"\t"+t3.getId());
System.out.println("----------浅克隆-----------");
System.out.println("t1:t3 "+t1.equals(t3));
System.out.println(t1);
System.out.println(t3);
t3.setName("李四");
System.out.println("修改后:");
System.out.println(t1.getName()+"\t"+t1.getId());
System.out.println(t3.getName()+"\t"+t3.getId());
}
}
下面这篇文章来自博客园YSOcean的讲解的十分清楚,让我受益匪浅。
https://www.cnblogs.com/ysocean/p/8482979.html
网友评论