2013-07-10 45 views
4

我在Java中拥有这段代码。关于在Java中克隆的困惑

public class CloneTest implements Cloneable{ 
    String name; 
    int marks; 
    public CloneTest(String s, int i) { 
     name = s; 
     marks = i; 
    } 

    public void setName(String s) { 
     name = s; 
    } 

    public void setMarks(int i) { 
     marks = i; 
    } 

    @Override 
    public Object clone() { 
     return new CloneTest(this.name, this.marks); 
    } 
} 

我创建了这个类的一个对象,然后克隆它。现在,当我在一个对象中更改name的值时,名称的值在另一个中保持不变。这里奇怪的是在构造函数中,我只是使用name的简单参考,而不是为name创建新的String。现在,由于String是参考类型,我预计克隆中的String也会被更改。谁能告诉我发生了什么事?提前致谢!

编辑

代码测试

CloneTest real = new CloneTest("Molly", 22); 
CloneTest clone = real.clone(); 
real.setName("Dolly"); 

我用BlueJ提供的 “检查变量” 功能来检查值。

+1

连包装类;) – NINCOMPOOP

+1

,如果在你的对象名的一个设置新名称获得对传入的字符串w的新引用其他对象保持参考 –

+0

字符串不可变,当您更改它时,会引用一个新字符串 – nachokk

回答

4

假设original是原CloneTest对象的名称,并cloned是您在使用clone()方法从original创建的克隆对象。

事情是这样的:
1.您cloned.nameoriginal.name在同一个对象,在这种情况下是一个字符串指向。
2.然后,您要求您的original.name指向不同的String对象(“Dolly”)。当您将新的String对象(“Dolly”)分配给参考original.name时,会发生这种情况。
3.但是,cloned.name仍然指向第一个String对象(“Dolly”)。

因此,仍然cloned.name打印第一字符串对象。

现在,如果您能够在不重新分配引用的情况下更改String对象的内容,那么clone.name中的更改将反映在original.name中。但对于String对象,由于Strings的不变性,这是不可能的。但是,您可以反映cloneoriginalStringBuffers之间的变化,可以这么说。看看为同此示例代码:https://gist.github.com/VijayKrishna/5967668

+2

不可变性与它无关。这只是参考变量的简单重新分配。也许是 – GriffeyDog

+0

。但是,如果它是一个int数组并且克隆对象的数组元素发生了变化呢? – vijay

+0

@vijay比这个更改在两个实例中都是可见的,因为只有一个包含2个引用的数组。 – jlordo

2

类的每个实例都有一个对象的不同引用。你只是改变引用而不是修改对象。如果你把你的字符串中的一些持有者对象,然后克隆它,并持有人(而不是持有人参考,但里面持有者串参考)内设置字符串,那么你就必须在两个克隆

0

的更改所以你是说你正在做类似:

public void testSomeMethod() { 

     CloneTest a = new CloneTest("a", 1); 

     CloneTest b = (CloneTest) a.clone(); 

     a.setName("b"); 

     assertFalse(b.name.equals(a.name)); 
     assertEquals("b", a.name); 
     assertEquals("a", b.name); 
    } 

如果是这样,那么所有这些断言都应该通过。你的克隆方法中有引用类型,并且在初始克隆时,它们引用同一个对象。但setName(“...”)更改实例指向的值,而不是所引用的对象的值。

0

通过查找哈希码,获得更好的清晰度以及@vijay答案。

CloneTest real = new CloneTest("Molly", 22); 
    CloneTest clone = (CloneTest) real.clone(); 
    int h1=real.name.hashCode(); 
    int h2=clone.name.hashCode(); 
    System.out.println("h1 " + h1 + " h2 " + h2); // same 
    real.setName("sak"); 
    h1=real.name.hashCode(); 
    h2=clone.name.hashCode(); 
    System.out.println("h1 " + h1 + " h2 " + h2); //different 

输出:

h1 74525175 h2 74525175 
h1 113629 h2 74525175 
0
package com.test; 
class Manager implements Cloneable 
{ 
String firstName; 
String lastName; 
int age; 
public Manager(String fname,String lname,int a) 
{ 
    this.firstName=fname; 
    this.lastName=lname; 
    this.age=a; 
} 
public String getFirstName() { 
    return firstName; 
} 
public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 
public String getLastName() { 
    return lastName; 
} 
public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 
public int getAge() { 
    return age; 
} 
public void setAge(int age) { 
    this.age = age; 
} 
@Override 
protected Object clone() throws CloneNotSupportedException { 
    // TODO Auto-generated method stub 
    return super.clone(); 
} 

}

public class TestCloning { 
public static void main(String[] args) throws CloneNotSupportedException { 
    Manager m1=new Manager("Sadik","Tahir",26); 
    Manager m_clone=(Manager)m1.clone(); 
    Manager m2=m1; 
    System.out.println("M1 Details:::"); 
    System.out.println("Fisrt Name:"+m1.getFirstName()+",LastName:"+m1.getLastName()+",Age:"+m1.getAge()); 
    System.out.println("Hashcode:"+m1.hashCode()); 
    System.out.println("M_Clone Details:::"); 
    System.out.println("Fisrt Name:"+m_clone.getFirstName()+",LastName:"+m_clone.getLastName()+",Age:"+m_clone.getAge()); 
    System.out.println("Hashcode:"+m_clone.hashCode()); 
    System.out.println("M2 Details:::"); 
    System.out.println("Fisrt Name:"+m2.getFirstName()+",LastName:"+m2.getLastName()+",Age:"+m2.getAge()); 
    System.out.println("Hashcode:"+m2.hashCode()); 
    m1.setFirstName("Afreen"); 
    m1.setLastName("Khan"); 
    m1.setAge(25); 
    System.out.println("M1 Details:::"); 
    System.out.println("Fisrt Name:"+m1.getFirstName()+",LastName:"+m1.getLastName()+",Age:"+m1.getAge()); 
    System.out.println("Hashcode:"+m1.hashCode()); 
    System.out.println("M_Clone Details:::"); 
    System.out.println("Fisrt Name:"+m_clone.getFirstName()+",LastName:"+m_clone.getLastName()+",Age:"+m_clone.getAge()); 
    System.out.println("Hashcode:"+m_clone.hashCode()); 
    System.out.println("M2 Details:::"); 
    System.out.println("Fisrt Name:"+m2.getFirstName()+",LastName:"+m2.getLastName()+",Age:"+m2.getAge()); 
    System.out.println("Hashcode:"+m2.hashCode()); 
} 

}