浅拷贝
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
简而言之,浅拷贝仅仅复制锁考虑的对象,而不复制它所引用的对象。
实现浅拷贝的步骤是:
1、被复制的类需要实现Cloneable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常)改接口为标记接口(不含任何方法)
2、覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,(native为本地方法)
深拷贝
深拷贝还要吧一个对象中所引用的对象也要拷贝一遍。
下面是一个例子:
123456789101112131415161718192021222324252627282930313233343536 |
package JavaCoreTechnology; import java.io.Serializable; /** * Created by benjamin on 1/14/16. */public class User implements Serializable, Cloneable { private static final long serialVersionUID = -3080870074068514966L; private String userName; private Dog dog; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } public User clone() throws CloneNotSupportedException { User user = (User)super.clone(); Dog d = dog.clone(); // 深拷贝必须克隆包含的对象 user.setDog(d); return user; }} |
123456789101112131415161718192021222324 |
package JavaCoreTechnology; import java.io.Serializable; /** * Created by benjamin on 1/14/16. */public class Dog implements Serializable, Cloneable { private static final long serialVersionUID = 8869944898908733919L; private String dogName; public String getDogName() { return dogName; } public void setDogName(String dogName) { this.dogName = dogName; } public Dog clone() throws CloneNotSupportedException { return (Dog)super.clone(); }} |
12345678910111213141516171819202122232425 |
package JavaCoreTechnology; /** * Created by benjamin on 1/14/16. */public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { User user = new User(); Dog dog = new Dog(); dog.setDogName("D1"); user.setUserName("A1"); user.setDog(dog); User user2 = user.clone(); user2.setUserName("A2"); user2.getDog().setDogName("D2"); System.out.println(user.getUserName()); // A1 System.out.println(user.getDog().getDogName()); // D1 System.out.println(user2.getUserName()); // A2 System.out.println(user2.getDog().getDogName()); // D2 }} |
可以发现上面已经成功的实现了深拷贝。但是试想一下,要是我一个类当中使用到了100个对象,那我也要一个个的去那些对象里面实现clone的方法吗,这显然有些太麻烦了。
为此,我们可以使用序列化对象的方法得到对象的一个拷贝。这就要用到了输入输出流。
修改一下代码,我们再来看一下:
去掉所有实体的Cloneable实现,以及clone方法:
1234567891011121314151617181920212223242526272829 |
package JavaCoreTechnology; import java.io.Serializable; /** * Created by benjamin on 1/14/16. */public class User implements Serializable { private static final long serialVersionUID = -3080870074068514966L; private String userName; private Dog dog; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; }} |
1234567891011121314151617181920 |
package JavaCoreTechnology; import java.io.Serializable; /** * Created by benjamin on 1/14/16. */public class Dog implements Serializable { private static final long serialVersionUID = 8869944898908733919L; private String dogName; public String getDogName() { return dogName; } public void setDogName(String dogName) { this.dogName = dogName; }} |
增加一个工具方法用来clone对象:
123456789101112131415161718192021222324252627282930313233 |
package JavaCoreTechnology; import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream; /** * Created by benjamin on 1/14/16. */public class ObjCloner { public static <T> T cloneObj(T obj) { T cloneVal = null; try { // 写入流中 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); // 从流中读入对象 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); cloneVal = (T)ois.readObject(); } catch (Exception e) { e.printStackTrace(); } return cloneVal; }} |
12345678910111213141516171819202122232425 |
package JavaCoreTechnology; /** * Created by benjamin on 1/14/16. */public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { User user = new User(); Dog dog = new Dog(); dog.setDogName("D1"); user.setUserName("A1"); user.setDog(dog); User user2 = ObjCloner.cloneObj(user); user2.setUserName("A2"); user2.getDog().setDogName("D2"); System.out.println(user.getUserName()); // A1 System.out.println(user.getDog().getDogName()); // D1 System.out.println(user2.getUserName()); // A2 System.out.println(user2.getDog().getDogName()); // D2 }} |
输出结果不变,总得看来,我更推荐大家使用流的方式来进行对象的深拷贝,不知道大家怎么看呢?
时间: 2024-10-31 21:30:06