黑马程序员技术交流社区
标题: 浅复制与深复制?? [打印本页]
作者: 陈振兴 时间: 2012-9-11 11:21
标题: 浅复制与深复制??
本帖最后由 陈振兴 于 2012-9-11 23:06 编辑
今天忽然看到日志中的Object中11种方法中的Clone方法,提及到的!
提问:浅复制与深复制在什么情况下使用,然后他们有效率问题,或者有代码重用功能吗?
浅复制:把原对象的基本属性复制,把对象的方法引用。
String name;
int age;
深复制:所有的都复制
浅复制能理解了,就像我们拷贝文件一样,把内容全部复制了。
而在java中,就相当于重新起了个名字,指向还是原对象属性的。专业术语:父类(同类)的对象引用子类的对象,他们的地址不变,这应该就是多态的底层了吧!
如:String[] ary1 = Arrays.copyOf(ary, ary.length);
调用java的底层数组进行复制,那么
深复制所有复制指的什么,这种应用在哪里会遇到?
作者: AngieFans85 时间: 2012-9-11 12:29
本帖最后由 马镱洵 于 2012-9-11 20:40 编辑
深复制:
一个对象的成员属性改变,不会影响到另一个对象相对应的成员属性.
实现方式:
1 实现Cloneable接口.
2 复写clone()方法.
3 在clone()方法的第一句调用super.clone();生成要复制的对象,在方法结尾要将这个对象返回出去.
4 在外部调用该重写后的clone()方法获得深复制后得到的对象.
浅复制:
一个对象的成员属性改变,会影响到另一个对象相对应的成员属性.
除了Arrays.copyOf()方法是浅复制外,System.arraycopy()方法和Arrays.copyOfRange()方法也是浅复制.
以上三个方法,自己去实验一下就是了.现在要介绍另外一种浅复制的方式,那就是在一个对象A中保存另一个对象B的引用,当复制对象A的时候(深复制),可以同时将对象B进行浅复制,见代码:- public class Person implements Cloneable {
- private String name;
- private Dog dog;
- public Person(String name) {
- this.name = name;
- }
- public Person(String name, Dog dog) {
- this.name = name;
- this.dog = dog;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Dog getDog() {
- return dog;
- }
- public void setDog(Dog dog) {
- this.dog = dog;
- }
- @Override
- public String toString() {
- return name + ":" + dog;
- }
- public static void print() {
- System.out.println("父类");
- }
- @Override
- public Object clone() throws CloneNotSupportedException {
- // 这个p就是最终复制的对象,这是深复制.
- Person p = (Person) super.clone();
- // Dog类是Person类的成员属性,所以以下代码是对Dog对象的浅复制.
- Dog dog = (Dog) getDog().clone();
- p.setDog(dog);
- // 返回复制后的对象
- return p;
- }
- }
复制代码- class Dog implements Cloneable {
- private String name;
- public Dog(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
复制代码
作者: 陈振兴 时间: 2012-9-11 20:49
马镱洵 发表于 2012-9-11 12:29 
深复制:
一个对象的成员属性改变,不会影响到另一个对象相对应的成员属性.
实现方式:
看那个API挺绕的!我再问一下在主方法中
public static void main(String[] args) throws CloneNotSupportedException{
P p = new P("zhangsan");
D d = new D("huahua");
P p1 =new P("lisi",new D("niu"));
System.out.println("p:"+p.clone()); p:zhangsan:null
System.out.println("p1:"+p1.clone()); p1:lisi:com.blackhorse.Test.D@199f91c
System.out.println(p.clone().getClass()==p1.clone().getClass()); true,这个true表示的是复制的内容相同吗?从上面两个值我觉得它的字节码是不同的呀,文档中
“并非满足的要求?”有点晕!他这个复制是不是把第一个name的构造方法中的值给修改了……
// System.out.println("d:"+d.clone());
}
这个让人看着真晕!
作者: AngieFans85 时间: 2012-9-11 21:48
陈振兴 发表于 2012-9-11 20:49 
看那个API挺绕的!我再问一下在主方法中
public static void main(String[] args) throws CloneNotSupport ...
"这个true表示的是复制的内容相同吗?从上面两个值我觉得它的字节码是不同的呀,文档中
“并非满足的要求?”有点晕!他这个复制是不是把第一个name的构造方法中的值给修改了……"
p和p1的都属于同一个Person类啊,所以:
System.out.println(p.clone().getClass()==p1.clone().getClass());
当然返回true了.这个true只表示他们属于同一个字节码文件(也就是说这两个对象属于同一个类),不表示复制的内容相同.
p.clone()方法代码把p的对象给整个复制了一分,包括p的成员属性,都是复制了一份.但有一点必须要注意,虽然p对象被复制了一份,但是p对象的成员属性如果是引用类型的话(比如说代码中的Dog就是Person的成员属性),p.clone()方法执行后,p对象的Dog成员只是浅拷贝,你如果把复制后的Person对象的Dog属性给修改了,那么复制前的原始p对象的Dog的属性也随之做相应的修改.
如果你只是把复制后的Person对象的非引用类型成员属性的值修改了,那么复制前的原始的p对象的非引用类型的成员属性的值并不会做相应的更改.
作者: 陈振兴 时间: 2012-9-11 23:05
马镱洵 发表于 2012-9-11 21:48 
"这个true表示的是复制的内容相同吗?从上面两个值我觉得它的字节码是不同的呀,文档中
“并非满足的要求 ...
ok!可能是这两天没休息好,今晚不在状态,还是道声谢谢!你14期吗?
作者: AngieFans85 时间: 2012-9-11 23:21
陈振兴 发表于 2012-9-11 23:05 
ok!可能是这两天没休息好,今晚不在状态,还是道声谢谢!你14期吗?
不客气,还不是14期学员.
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |