2013-07-10 71 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()); 
} 

}