Java的深浅拷贝机制
我们先理解一下深浅拷贝的概念
1.浅拷贝:Java在进行对象拷贝的过程中,对于他的成员变量进行拷贝,如果是基本数据类型,就会直接拷贝他的值。如果是引用类型,则会拷贝他的引用地址,而不会拷贝对象本身
2.深拷贝:Java在进行对象拷贝的过程中,对于他的成员变量进行拷贝,如果是基本数据类型,就会直接拷贝他的值。如果是引用类型,不仅会会拷贝他的引用地址,还会拷贝对象本身。
有三种方式实现Java的深浅拷贝机制。
1.用 = 实现(代码示例)
浅拷贝:
List<Integer> oldObj = new ArrayList<>();
oldObj.add(1);
List<Integer> newObj = oldObj;
newObj.add(2);
System.out.println("拷贝前:\t" + oldObj);
System.out.println("拷贝后:\t" + newObj);
执行结果:
从执行结果可以清晰的看到,拷贝后改变对象后,拷贝前的对象也随之改变。
深拷贝
List<Integer> oldObj = new ArrayList<>();
oldObj.add(1);
List<Integer> newObj = new ArrayList<>(oldObj);
newObj.add(2);
System.out.println("拷贝前:\t" + oldObj);
System.out.println("拷贝后:\t" + newObj);
执行结果
2.对象实现cloneable接口,重写clone()方法
这种拷贝的方法比较快,方法直接在内存中执行
浅拷贝
public class ShallowCopy {
public static void main(String[] args) {
Animal oldAnimal = new Animal("狗",new Dog("二哈"));
Animal cloneAnimal = null;
try {
cloneAnimal = oldAnimal.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
//改变拷贝前的属性值
oldAnimal.setName("动物");
oldAnimal.getDog().setName("拉布拉多");
System.out.println("拷贝前:\t" + oldAnimal);
System.out.println("拷贝后: \t" + cloneAnimal);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal implements Cloneable {
private String name;
private Dog dog;
@Override
protected Animal clone() throws CloneNotSupportedException {
Animal animal = null;
animal = (Animal) super.clone();
animal.setDog(animal.getDog());
return animal;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Dog {
private String name;
}
执行结果
深拷贝
public class DeepCopy {
public static void main(String[] args) {
Animal oldAnimal = new Animal("狗",new Dog("二哈"));
Animal cloneAnimal = null;
try {
cloneAnimal = oldAnimal.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
//改变拷贝前的属性值
oldAnimal.setName("动物");
oldAnimal.getDog().setName("拉布拉多");
System.out.println("拷贝前:\t" + oldAnimal);
System.out.println("拷贝后: \t" + cloneAnimal);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal implements Cloneable {
private String name;
private Dog dog;
@Override
protected Animal clone() throws CloneNotSupportedException {
Animal animal = null;
animal = (Animal) super.clone();
animal.setDog(animal.getDog().clone());
return animal;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Dog implements Cloneable{
private String name;
@Override
protected Dog clone() throws CloneNotSupportedException {
return (Dog)super.clone();
}
}
执行结果
3.序列化拷贝(只能深拷贝)
把对象写入到流中,用的时候再取出来
需要序列化的类一定要实现Serializable接口,不然会报错java.io.NotSerializableException
public class SerialCopy {
public static void main(String[] args) {
Animal oldAnimal = new Animal("小狗", new Dog("二哈"));
Animal cloneAnimal = (Animal)clone(oldAnimal);
oldAnimal.setName("动物");
oldAnimal.getDog().setName("拉布拉多");
System.out.println("拷贝前:\t" + oldAnimal);
System.out.println("拷贝后: \t" + cloneAnimal);
}
public static Object clone(Object obj){
Object cloneObj = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
cloneObj = ois.readObject();
ois.close();
}catch (Exception e){
throw new RuntimeException();
}
return cloneObj;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal implements Serializable{
private String name;
private Dog dog;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Dog implements Serializable{
private String name;
}
执行结果