目录
概念
浅拷贝(浅复制、浅克隆):
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所拷贝的对象,而不复制它所引用的对象。
深拷贝(深复制、深克隆):
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍
浅拷贝快速入门例子(不带对象属性)
public class Student {
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = stu1;
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
System.out.println(stu1 == stu2);
stu2.setNumber(22222);
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
}
}
输出结果
学生1:12345
学生2:12345
true
学生1:22222
学生2:22222
深拷贝快速入门例子(不带对象属性)
public class Student implements Cloneable {
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = null;
try {
stu2 = (Student) stu1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
System.out.println(stu1 == stu2);
stu2.setNumber(22222);
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
}
}
结果
学生1:12345
学生2:12345
false
学生1:12345
学生2:22222
属性未实现Cloneable 例子(浅拷贝)
class Address {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
}
class Student2 implements Cloneable {
private int number;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student2 stu = null;
try {
stu = (Student2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
public static void main(String args[]) {
Address addr = new Address();
addr.setAdd("杭州市");
Student2 stu1 = new Student2();
stu1.setNumber(123);
stu1.setAddr(addr);
Student2 stu2 = (Student2) stu1.clone();
stu1.setNumber(3333);
stu1.getAddr().setAdd("中国");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
System.out.println(stu1.getAddr() == stu2.getAddr());
}
}
输出结果
学生1:3333,地址:中国
学生2:123,地址:中国
true
属性实现Cloneable 例子-未显示调用属性的clone(浅拷贝)
class Address implements Cloneable {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
@Override
public Object clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
}
class Student2 implements Cloneable {
private int number;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student2 stu = null;
try {
stu = (Student2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
public static void main(String args[]) {
Address addr = new Address();
addr.setAdd("杭州市");
Student2 stu1 = new Student2();
stu1.setNumber(123);
stu1.setAddr(addr);
Student2 stu2 = (Student2) stu1.clone();
stu1.setNumber(3333);
stu1.getAddr().setAdd("中国");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
System.out.println(stu1.getAddr() == stu2.getAddr());
}
输出结果
学生1:3333,地址:中国
学生2:123,地址:中国
true
属性实现Cloneable 例子(深拷贝)
// clone时,需要调用对象属性的clone
stu.addr = (Address) addr.clone();
class Address implements Cloneable {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
@Override
public Object clone() {
Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return address;
}
}
class Student2 implements Cloneable {
private int number;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student2 stu = null;
try {
stu = (Student2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// 对象属性设置
stu.addr = (Address) addr.clone();
return stu;
}
public static void main(String args[]) {
Address addr = new Address();
addr.setAdd("杭州市");
Student2 stu1 = new Student2();
stu1.setNumber(123);
stu1.setAddr(addr);
Student2 stu2 = (Student2)stu1.clone();
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
stu1.setNumber(222);
addr.setAdd("西湖区");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
}
}
测试结果
学生1:123,地址:杭州市
学生2:123,地址:杭州市
学生1:222,地址:西湖区
学生2:123,地址:杭州市
序列化实现(深拷贝)
class Book implements Serializable {
private static final long serialVersionUID = 8234484588726379017L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Book [name=" + name + "]";
}
}
class Teacher implements Serializable {
private static final long serialVersionUID = -7471815149371769182L;
private int no;
private Book book;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
@Override
public String toString() {
return "Teacher [no=" + no + ", book=" + book + "]";
}
public static void main(String[] args) throws Exception {
// 序列化
Book book = new Book();
book.setName("语文");
Teacher teacher = new Teacher();
teacher.setNo(10001);
teacher.setBook(book);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(teacher);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// 反序列化
ObjectInputStream ois = new ObjectInputStream(bais);
Teacher teacher2 = (Teacher) ois.readObject();
System.out.println(teacher == teacher2);
System.out.println("老师1:" + teacher.getNo() + ",学科:" + teacher.getBook().getName());
System.out.println("老师2:" + teacher2.getNo() + ",学科:" + teacher2.getBook().getName());
teacher.setNo(2222);
teacher.getBook().setName("数学");
System.out.println("老师1:" + teacher.getNo() + ",学科:" + teacher.getBook().getName());
System.out.println("老师2:" + teacher2.getNo() + ",学科:" + teacher2.getBook().getName());
}
}
测试结果
false
老师1:10001,学科:语文
老师2:10001,学科:语文
老师1:2222,学科:数学
老师2:10001,学科:语文
序列化实现(浅拷贝,单例)
需要重写方法private Object readResolve() throws ObjectStreamException
,返回单例实例对象
public class Teacher2 implements Serializable {
private static final long serialVersionUID = -7471815149371769182L;
private int no;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
@Override
public String toString() {
return "Teacher [no=" + no + "]";
}
private static final Teacher2 INSTANCE = new Teacher2();
private Teacher2() {}
public static Teacher2 getInstance() {
return INSTANCE;
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
public static void main(String[] args) throws Exception {
// 序列化
Teacher2 teacher = Teacher2.getInstance();
teacher.setNo(10001);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(teacher);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// 反序列化
ObjectInputStream ois = new ObjectInputStream(bais);
Teacher2 teacher2 = (Teacher2) ois.readObject();
System.out.println(teacher == teacher2);
System.out.println("老师1:" + teacher.getNo());
System.out.println("老师2:" + teacher2.getNo());
teacher.setNo(2222);
System.out.println("老师1:" + teacher.getNo());
System.out.println("老师2:" + teacher2.getNo());
}
}
测试结果
true
老师1:10001
老师2:10001
老师1:2222
老师2:2222