1.为什么要使用克隆?
- 想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中的克隆针对的是类的实例。
2.如何实现对象克隆?
有以下两种方法:
- 1.实现Cloneable接口并重写Object的clone方法。
- 2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的克隆,代码如下:
package com.springCloud.consumer.controller;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import java.io.*;
/**
* 克隆工具类
*/
public class MyUtil {
private MyUtil(){
throw new AssertionError();
}
@SuppressWarnings("unchecked")
//此注解告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
public static <T extends Serializable> T clone(T obj) throws Exception{
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();
// 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
}
}
/*Person类*/
@Data
@AllArgsConstructor
@ToString
class Person implements Serializable{
private static final long serialVersionUID = -9102017020286042305L;
private String name;
private int age;
private Car car;
}
/*Car类*/
@Data
@AllArgsConstructor
@ToString
class Car implements Serializable{
private static final long serialVersionUID = -5713945027627603702L;
private String brand;
private int maxSpeed;
}
/**
* 克隆测试类
*/
class CloneTest{
public static void main(String[] args) {
Person p1 = new Person("张三",22,new Car("Benz",300));
try {
Person p2 = MyUtil.clone(p1);
p2.getCar().setBrand("BYD");
p2.getCar().setMaxSpeed(180);
System.out.println("p1 = " + p1);
System.out.println("----------");
System.out.println("p2 =" + p2);
/*修改克隆的Person对象p2关联的汽车对象的品牌属性
原来的Person对象p1关联的汽车不会受到任何影响
因为在克隆Person对象时其关联的汽车对象也被克隆了*/
} catch (Exception e) {
e.printStackTrace();
}
}
/*输出结果:
p1 = Person(name=张三, age=22, car=Car(brand=Benz, maxSpeed=300))
----------
p2 =Person(name=张三, age=22, car=Car(brand=BYD, maxSpeed=180))*/
}
3.深拷贝和浅拷贝的区别是什么?
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中一个对象的某个值,另外一个对象的对应值都会随之变化,这就是浅拷贝(例:assign())。
- 深拷贝是将对象和值复制过来,修改其中一个对象的某个值,另外一个对象的对应值不会随之改变,这就是深拷贝(例:JSON.parse()和JSON.stringify()方法)