A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈振兴 中级黑马   /  2012-9-11 11:21  /  3815 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈振兴 于 2012-9-11 23:06 编辑

今天忽然看到日志中的Object中11种方法中的Clone方法,提及到的!
提问:浅复制与深复制在什么情况下使用,然后他们有效率问题,或者有代码重用功能吗?
浅复制:把原对象的基本属性复制,把对象的方法引用。
String name;
int age;
深复制:所有的都复制
浅复制能理解了,就像我们拷贝文件一样,把内容全部复制了。

而在java中,就相当于重新起了个名字,指向还是原对象属性的。专业术语:父类(同类)的对象引用子类的对象,他们的地址不变,这应该就是多态的底层了吧!
如:String[] ary1 = Arrays.copyOf(ary, ary.length);

调用java的底层数组进行复制,那么
深复制所有复制指的什么,这种应用在哪里会遇到?


评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

5 个回复

倒序浏览
本帖最后由 马镱洵 于 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进行浅复制,见代码:
  1. public class Person implements Cloneable {

  2.         private String name;
  3.         private Dog dog;

  4.         public Person(String name) {
  5.                 this.name = name;
  6.         }

  7.         public Person(String name, Dog dog) {
  8.                 this.name = name;
  9.                 this.dog = dog;
  10.         }

  11.         public String getName() {
  12.                 return name;
  13.         }

  14.         public void setName(String name) {
  15.                 this.name = name;
  16.         }

  17.         public Dog getDog() {
  18.                 return dog;
  19.         }

  20.         public void setDog(Dog dog) {
  21.                 this.dog = dog;
  22.         }

  23.         @Override
  24.         public String toString() {
  25.                 return name + ":" + dog;
  26.         }

  27.         public static void print() {
  28.                 System.out.println("父类");
  29.         }

  30.         @Override
  31.         public Object clone() throws CloneNotSupportedException {
  32.                 // 这个p就是最终复制的对象,这是深复制.
  33.                 Person p = (Person) super.clone();

  34.                 // Dog类是Person类的成员属性,所以以下代码是对Dog对象的浅复制.
  35.                 Dog dog = (Dog) getDog().clone();
  36.                 p.setDog(dog);

  37.                 // 返回复制后的对象
  38.                 return p;
  39.         }

  40. }
复制代码
  1. class Dog implements Cloneable {

  2.         private String name;

  3.         public Dog(String name) {
  4.                 this.name = name;
  5.         }

  6.         public String getName() {
  7.                 return name;
  8.         }

  9.         public void setName(String name) {
  10.                 this.name = name;
  11.         }

  12.         @Override
  13.         public Object clone() throws CloneNotSupportedException {
  14.                 return super.clone();
  15.         }

  16. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
马镱洵 发表于 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());
        }
这个让人看着真晕!
回复 使用道具 举报
陈振兴 发表于 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 21:48
"这个true表示的是复制的内容相同吗?从上面两个值我觉得它的字节码是不同的呀,文档中
“并非满足的要求 ...

ok!可能是这两天没休息好,今晚不在状态,还是道声谢谢!你14期吗?
回复 使用道具 举报
陈振兴 发表于 2012-9-11 23:05
ok!可能是这两天没休息好,今晚不在状态,还是道声谢谢!你14期吗?

不客气,还不是14期学员.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马