使用复制也就是克隆必须要实现Cloneable接口,
public interface Cloneable {} 发现这又是一个标记接口,还有就是要重写Object类中的clone()方法package com.prototype;
public class Student implements Cloneable {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
测试:
package com.prototype;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Student stu = new Student("zhouguizhi", 18);
System.out.println("stu="+stu);
Student cloneStu = (Student) stu.clone();
System.out.println("cloneStu="+cloneStu);
System.out.println("name="+cloneStu.getName()+"--"+"age="+cloneStu.getAge());
}
}
运行结果:
其实克隆就是类似这种把一个对象中的值赋值给另外一个对象,比如这样子:
Student stu = new Student("zhouguizhi", 18);
System.out.println("stu="+stu);
Student cloneStu = new Student();
cloneStu.setName(stu.getName());
cloneStu.setAge(stu.getAge());
这是这种效率比较低而已,所以java会把克隆也就是clone()方法放在native层,用c处理起来效率更高.
现在Student类上添加一个朋友的属性对象
package com.prototype;
public class Student implements Cloneable {
private String name;
private int age;
private Friend friend;
public Student(String name, int age, Friend friend) {
super();
this.name = name;
this.age = age;
this.friend = friend;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
public Friend getFriend() {
return friend;
}
public void setFriend(Friend friend) {
this.friend = friend;
}
class Friend{
private int age;
private String name;
public Friend(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Test.java
package com.prototype;
import com.prototype.Student.Friend;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Friend friend =new Student().new Friend(20,"xiaofang");
System.out.println("friend="+friend);
Student stu = new Student("zhouguizhi", 18,friend);
Student cloneStu = (Student) stu.clone();
Friend cloneFriend = cloneStu.getFriend();
System.out.println("克隆后的friend="+friend);
cloneFriend.setAge(99);//改变Friend对象中的值
//获取原数据fried对象中的age值
System.out.println("age="+friend.getAge());
}
}
运行结果:
friend=com.prototype.Student$Friend@2a139a55克隆后的friend=com.prototype.Student$Friend@2a139a55age=99
从打印的结果看,明明是在克隆后的Student对象上获取到Friend对象后改变了age的值,但是原来的值也跟着改变了,说明了这个Friend对象在内存中是共享同一个对象才会造成这样结果
浅克隆:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象
从上面的问题就引出了深克隆的问题
深克隆:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制(会创建对象在内存中分配就不一样)
对于上面的问题用深克隆可以解决
再次看下Student类的代码:
package com.prototype;
public class Student implements Cloneable {
private String name;
private int age;
private Friend friend;
public Student(String name, int age, Friend friend) {
super();
this.name = name;
this.age = age;
this.friend = friend;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Student student = (Student) obj;
student.friend = (Friend) this.friend.clone();//把属性也进行克隆
return obj;
}
public Friend getFriend() {
return friend;
}
public void setFriend(Friend friend) {
this.friend = friend;
}
class Friend implements Cloneable {
private int age;
private String name;
public Friend(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
}
Test.java
package com.prototype;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Friend friend =new Friend(20,"xiaofang");
System.out.println("friend="+friend);
Student stu = new Student("zhouguizhi", 18,friend);
Student cloneStu = (Student) stu.clone();
Friend cloneFriend = cloneStu.getFriend();
System.out.println("克隆后的friend="+cloneFriend);
cloneFriend.setAge(99);//改变Friend对象中的值
//获取原数据fried对象中的age值
System.out.println(friend==cloneFriend);
System.out.println("age="+friend.getAge());
}
}
运行结果:
friend=com.prototype.Friend@2a139a55
克隆后的friend=com.prototype.Friend@15db9742falseage=20
从结果上看发现friend和克隆出来的cloneFriend对象不是同一个对象了,而且改变克隆后的值也不会影响之前的值了.
从深克隆中发现也用到了浅克隆,上面的Friend对象重写了clone()方法就是浅克隆了,说明克隆可以多层嵌套.
其实使用序列化和反序列化也可以实现深克隆
package com.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Student implements Cloneable,Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private Friend friend;
public Student(String name, int age, Friend friend) {
super();
this.name = name;
this.age = age;
this.friend = friend;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Friend getFriend() {
return friend;
}
public void setFriend(Friend friend) {
this.friend = friend;
}
/**
* 序列化和反序列化实现深克隆
*/
public Object deepClone() throws Exception {
//将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
Test.java
package com.prototype;
public class Test {
public static void main(String[] args) throws Exception {
Friend friend =new Friend(20,"xiaofang");
System.out.println("friend="+friend);
Student stu = new Student("zhouguizhi", 18,friend);
Student student = (Student)stu.deepClone();
Friend cloneFriend = student.getFriend();
System.out.println("克隆后的cloneFriend="+cloneFriend);
cloneFriend.setAge(18);//原来是20 改为18
System.out.println("原friend中的age值="+friend.getAge());
}
}
运行结果:
friend=com.prototype.Friend@2a139a55
克隆后的cloneFriend=com.prototype.Friend@4554617c
原friend中的age值=20