2014-12-07 63 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 受到同样的问题,原语被自动写入到不可变的共享单个副本文字中。

所以,如果你想让你的存储数组的内容反映你修改后的数组以外的修改使用可变对象。并且,请注意自动化自动装箱陷入不可变对象文字。

相关问题