2014-12-07 32 views
0

我編寫了一些代碼來理解如果將原始對象,可變對象或不可變對象存儲到Array對象中會發生什麼情況。我可否在存儲後修改它們,看看它是否正確解除了這些事情並返回了修改後的值。我沒有得到我期望的代碼要做的事情?我想我知道爲什麼,並且想澄清這種理解是否正確。這是代碼。瞭解對Java Object Object中對象的引用

public class DriverApp3 { 

private static String CYEAR = "2014" ; 
private static StringBuffer CYEARFLG = new StringBuffer("1914") ; 

public double money = 2.13 ; 

public static void main(String args[]) 
{ 
    Integer j = 12 ; 
    DriverApp3 d = new DriverApp3(); 
    StringBuffer sb = new StringBuffer("Unicorn"); 
    MutableInteger mi = new MutableInteger(67); 
    int i = 76 ; 

    Object[] parseXML = new Object[]{j,DriverApp3.CYEAR,d, d.money,DriverApp3.CYEAR, sb, mi, DriverApp3.CYEARFLG,i}; 

    //        0   1  2  3  4    5 6   7   8 
    System.out.println("======chng of all original values =========="); 
    j = 13 ; 
    d.money = 3.14 ; 
    parseXML[4]="2015"; 
    DriverApp3.CYEAR = "2013"; 
    mi.set(9); 
    sb.replace(3,5,"KO"); 
    DriverApp3.CYEARFLG.replace(0,4,"1939"); 
    i = 7 ; 

    Object[] chngdO = new Object[]{j,DriverApp3.CYEAR,d, d.money,DriverApp3.CYEAR, sb, mi, DriverApp3.CYEARFLG,i}; 

    int cnt = 0 ; 
    for (Object m : parseXML) 
    { 
     Integer s_objid = m.hashCode(); 
     String clsType = "Type="+m.getClass().getTypeName(); 
     String clsName = "SimplName="+m.getClass().getSimpleName(); 
     String canName = "CanonName="+m.getClass().getCanonicalName(); 

     Object n = chngdO[cnt]; 
     Integer ns_objid = n.hashCode(); 
     String nclsType = "Type="+n.getClass().getTypeName(); 
     String nclsName = "SimplName="+n.getClass().getSimpleName(); 
     String ncanName = "CanonName="+n.getClass().getCanonicalName(); 


     System.out.println(cnt + ": Hashcode=" + s_objid + ":" + clsType + ":" + m + "\n " + ": Hashcode=" + ns_objid + ":" + nclsType /*+ ":"+ clsName+ ":"+ canName*/+ ":" + n + "\n"); 
     cnt++ ; 
    } 

} 

@Override 
public String toString() 
{ 

    return "Hashcode="+this.hashCode() + "," + DriverApp3.CYEAR ; 
} 

}

的可變類也在這裏.....

/** * * 從stackoverflow.com @author代碼片段*不是線程安全的 */ 公共類MutableInteger {

private int value; 
public MutableInteger(int value) { 
    this.value = value; 
} 
public void set(int value) { 
    this.value = value; 
} 
public int intValue() { 
    return value; 
} 

public String toString() 
{ 
    return "id="+this.hashCode()+" val=" + this.value ; 
} 

}

我的應用程序的輸出是.....

======chng of all original values ========== 

0:Hashcode方法= 12:種類= java.lang.Integer中:12 :Hashcode方法= 13:種類= java.lang.Integer中:13

1:Hashcode方法= 1537249:種類= java.lang.String中:2014 :Hashcode方法= 1537248:種類= java.lang.String中:2013

2:Hashcode方法= 366712642:種類= Xander的。 DirRefOrCopy.DriverApp3:Hashcode = 366712642,2013 :Hashcode = 366712642:Type = xander.DirRefOrCopy.DriverApp3:哈希碼= 366712642,2013

3:哈希碼= 815979831:種類= java.lang.Double中:2.13 :哈希碼= 300063655:種類= java.lang.Double中:3.14

4:哈希碼= 1537250:類型= java.lang.String中:2015年 :Hashcode方法= 1537248:種類= java.lang.String中:2013

5:Hashcode方法= 1829164700:種類= java.lang.StringBuffer中:UniKOrn :Hashcode方法= 1829164700:種類= java.lang.StringBuffer:UniKOrn

6:Hashcode = 2018699554:Type = xander.DirRefOrCopy.MutableInteger:id = 2018699554 val = 9 :Hashcode方法= 2018699554:種類= xander.DirRefOrCopy.MutableInteger:ID = 2018699554 VAL = 9

7:Hashcode方法= 1311053135:種類= java.lang.StringBuffer中:1939年 :Hashcode方法= 1311053135:種類= java.lang中.StringBuffer:1939

8:Hashcode方法= 76:種類= java.lang.Integer中:76 :Hashcode方法= 7:種類= java.lang.Integer中:7

回答

0

索引0 對於整數j,它是不可變的,所以只要我在數組之外修改它,第0個指針仍然指向值爲12的那個,因爲它在Java保持它對於該整數是不可變的單個副本的任何地方仍然活着。這顯然是一個爲每個類或接口保留所有運行時常量的區域。在這種情況下,它是字符串文字區域。修正後的j指向一個新的不可變單值拷貝值13.請參閱不同的哈希碼。

索引1 與上述相同的問題。僅僅因爲它是DriverApp3的成員,你本來會希望修改它自己,但它並不是因爲數組在Java存儲單個不可變副本的地方存儲了內存地址String的舊值。因爲那個地址仍然是「活着的」,它一直指向數組中的內存地址。非常非常不直觀 - 不確定是否有其他模式或語言更好地處理這種情況。這可能是錯誤的根源。要確保你反映了你的改變 - 然後在其中使用MUTABLE objs而不是IMMUTABLE。或者,您必須額外思考開銷,因爲必須記住Java可能會將您的原語(如果您正在存儲原語)自動複製到對象字面值,具體取決於它是否是字符串,整型,雙精度等。

索引2 一切都按預期工作 - 它指向陣列。所以,當它改變時,它繼續指向相同的可變對象地址。

索引3 再次,雙重自動複製到一個不可變的雙。所以,它是像String和Integer一樣的問題,因爲它是一個Object Array。當然,自從Java 1以來就像這樣 - btw - 我在這裏使用Java 8編譯器。

索引4 parseXML [4] =「2015」; 那麼這裏我們直接與不變的字符串文字的地址重寫地址2015年

指數5 的StringBuffer和MutableInteger正確反映的修正,因爲他們仍然指向同一個地址。 Java不會創建新副本,因爲它們的定義本質上是可變的。

索引7 反映更改,因爲它是可變的StringBuffer而不是共享的不可變字面!

索引8 受到同樣的問題,原語被自動寫入到不可變的共享單個副本文字中。

所以,如果你想讓你的存儲數組的內容反映你修改後的數組以外的修改使用可變對象。並且,請注意自動化自動裝箱陷入不可變對象文字。

相關問題