class Person implements Cloneable{
  private String name;
  private Car car;
  
  Person(String s,String t){
   name=s;
   car=new Car(t);
  }   public Car getCar(){
  return car;
 }
  public  String getName(){
   return name;
  }
  
  public void setName(String s){
    name=s;
  }
 
  public Object clone(){
    try{
    return super.clone();
    }catch(CloneNotSupportedException e){
    return null;
   }
}
}
//-------------------------------------
 class Car{
  private String name;
  
  public Car(String s){
  name=s;
  }
  public String getName(){
    return name;
  }
  public void setName(String s){
  name=s;
  }
 }

//-----------------------------
public class Test{
public static void main(String [] args){
   Person p=new Person("PersonA","car1");
   Person q=(Person)p.clone();
       q.setName("PersonB");
       q.getCar().setName("car2");
   
       System.out.println(p.getName()+";"+p.getCar().getName());
  
}
}
// 这是java设计模式原型中的一段代码,还是不明白结果为何是这样。请高手指点

解决方案 »

  1.   

    q只复制了car的引用(类似指针的地址似的),所以q实际上还是指向p里的car对象.改q的car相当于改p的car
      

  2.   

    这段代码实际上是向你展示了java里面默认的clone函数实际上是浅复制。 什么是浅复制呢? 浅复制就是把当前对象在内存中的数据结构复制一份, 但是并不复制当前对象多饮用的对象。在这个例子中,复制之前内存中的结构是这样的
    p
    -------------
    |  name  ---|-------> "Person1"     -----------
    |  car   ---|---------------------->|  name ---|------->"car1"
    -------------                       ------------ 复制之后的内存结构是这样的
    p
    -------------
    |  name  ---|-> "Person1"           -----------
    |  car   ---|/--------------------->|  name ---|------->"car1"
    ------------/                     / ------------ 
               /                     /
    q         /                     /
    ---------/---                  /
    |  name /   |                 /     
    |  car   ---|----------------/
    -------------                        
    也就是说, 签复制之后, 虽然生成了一个新的对象, 但是里面的name和car还都是指向原来的String和Car对象的
    所以, 在你操作q的时候, 对原来的p对象是有影响的, 
    当你q.setName的时候, 由于String是final的, 无法修改他的值, 因此会在内存中创建一个新的String, 所以p的name没有变化
    但是q.getCar的时候, 返回的仍然是p指向的Car对象, 所以q.getCar().setName()也修改了p引用的Car对象一般来说, 浅复制是一种危险的操作, 会对程序产生不可预测的影响, 一般方式是重载clone方法实现深度复制, 深度复制不仅仅是复制对象的引用, 也要复制引用的对象本身, 上面的例子经过深度复制之后, 内存结果应该是这样的
    p
    -------------
    |  name  ---|-------> "Person1"     -----------
    |  car   ---|---------------------->|  name ---|------->"car1"
    -------------                       ------------ 
    q
    -------------
    |  name  ---|-------> "Person1"     -----------
    |  car   ---|---------------------->|  name ---|------->"car1"
    -------------                       ------------ 
    这样对q操作, 就不会对p有任何影响了