文章目录
- 克隆
- 浅拷贝
- 深拷贝
克隆
Java实现克隆需要遵循以下规则:
1.必须实现Cloneable接口
2.实现Cloneable的类应该重写clone(),重写时该方法的修饰符为public。
浅拷贝
是将原始对象中的数据型字段拷贝到新对象中去,将引用型字段的“引用”复制到新对象中去,不把“引用的对象”复制进去,所以原始对象和新对象引用同一对象,新对象中的引用型字段发生变化会导致原始对象中的对应字段也发生变化。
public class Person implements Cloneable {
private String name;
private int age;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
//clone是浅拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// //深拷贝
// @Override
// protected Object clone() throws CloneNotSupportedException {
// String name = new String(this.name);
// return new Person(23, name);
// }
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(23, "李四");
Person person2 = (Person) person1.clone();//浅拷贝
// Person person2 = (Person) person1.clone();//深拷贝
String result = person1.getName() == person2.getName() ? "clone是浅拷贝" : "clone是深拷贝";
System.out.println(result);
}
}
当person1的属性和person2的属性相同时,就是浅拷贝。对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,不会对内存中的对象进行改变。
深拷贝
是在引用方面不同,深拷贝就是创建一个新的和原始字段的内容相同的字段,是两个一样大的数据段,所以两者的引用是不同的,之后的新对象中的引用型字段发生改变,不会引起原始对象中的字段发生改变。
public class Person implements Cloneable {
private String name;
private int age;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
//clone是浅拷贝
// @Override
// protected Object clone() throws CloneNotSupportedException {
// return super.clone();
// }
//深拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
String name = new String(this.name);
return new Person(23, name);
}
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(23, "李四");
// Person person2 = (Person) person1.clone();//浅拷贝
Person person2 = (Person) person1.clone();//深拷贝
String result = person1.getName() == person2.getName() ? "clone是浅拷贝" : "clone是深拷贝";
System.out.println(result);
}
}
当person1的属性和person2的属性不同时,就是深拷贝。对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,当复制了内容并对即使没有进行修改,其内存对应的地址也是不同的,就是说再内存中重新开辟了一块地址取存放。
深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。
深拷贝的另一种实现方式:进行序列化
import com.sun.corba.se.impl.io.OutputStreamHook;
import org.junit.Test;
import java.io.*;
/**
* @author lenovo
*/
public class ObjectInputOutputStreamTest {
@Test
public void test01(){
//序列化,写入到内存层面,防止被删除
ObjectOutputStream oos =null;
try {
//1.造对象
oos =new ObjectOutputStream(new FileOutputStream("Object.txt"));
//2.造流, 存储和读取基本数据类型数据或对象的处理流 ,这里为对象
oos.writeObject(new String("小猫咪喵喵喵"));
//3.注意写出一次,操作flush()一次 ,刷新操作
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (oos !=null)
//4.关闭
{
try {
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Test
public void test02(){
//反序列化
ObjectInputStream ois = null;
try {
//1.造对象
ois = new ObjectInputStream(new FileInputStream("Object.txt"));
//2.造流
Object o = ois.readObject();
String str = (String) o;
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}if(ois !=null)
//3.关闭,没有刷新
{
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}