我编写了一些代码来理解如果我将一个基元,对象可变或不可变的混合存储到Array对象中会发生什么。我可以在存储后对它们进行修改,看看它是否正确解除引用这些内容并返回修改后的值。我没有得到我的预期代码要做的事情?我想我知道为什么,并想澄清这种理解是否正确。这是代码。
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:Type = java.lang.Integer:12 :Hashcode = 13:Type = java.lang.Integer:13
1:Hashcode = 1537249:Type = java.lang.String:2014 :Hashcode = 1537248:Type = java.lang.String:2013
2:Hashcode = 366712642:Type = xander.DirRefOrCopy.DriverApp3:Hashcode = 366712642,2013 :Hashcode = 366712642:Type = xander.DirRefOrCopy.DriverApp3:Hashcode = 366712642,2013
3:Hashcode = 815979831:Type = java.lang.Double:2.13 :Hashcode = 300063655:Type = java.lang.Double:3.14
4:Hashcode = 1537250:Type = java.lang.String:2015 :Hashcode = 1537248:Type = java.lang.String:2013
5:Hashcode = 1829164700:Type = java.lang.StringBuffer:UniKOrn :Hashcode = 1829164700:Type = java.lang.StringBuffer:UniKOrn
6:Hashcode = 2018699554:Type = xander.DirRefOrCopy.MutableInteger:id = 2018699554 val = 9 :Hashcode = 2018699554:Type = xander.DirRefOrCopy.MutableInteger:id = 2018699554 val = 9
7:Hashcode = 1311053135:Type = java.lang.StringBuffer:1939 :Hashcode = 1311053135:Type = java.lang.StringBuffer:1939
8:Hashcode = 76:Type = java.lang.Integer:76 :Hashcode = 7:Type = java.lang.Integer:7
答案 0 :(得分:0)
指数0 对于Integer j,它是不可变的,所以一旦我在数组外部修改它,第0个仍然指向值为12的那个,因为它仍然存在于Java保持它的整个Integer的不可变单个副本的地方。这显然是一个保持每个类或接口的所有运行时常量的区域。在这种情况下,它是字符串文字区域。修正后的j指向一个值为13的新的不可变单个副本。参见Hashcodes也不同。
指数1 像上面一样的问题。仅仅因为它是DriverApp3的一个成员,你本来希望自己修改它,但它不会因为数组在java存储该不可变的单个副本的地方存储了旧的内存地址字符串值。因为,该地址仍然是“活着的”,它一直指向数组中的内存地址。非常非直观 - 不确定是否有其他模式或语言可以更好地处理这个问题。它可能是错误的来源。想要确保你反映你的变化 - 在其中使用MUTABLE obj而不是IMMUTABLE。或者,您还需要记住,Java可能会将您的基元(如果存储基元)Autobox Autobox放入Object文本中,具体取决于它是String,Integer,Double等。
指数2 一切都按预期工作 - 它指向数组。因此,它在更改时继续指向相同的可变对象地址。
指数3 Double再次将Autoboxed变为不可变的Double。因此,它与String和Integer是同一个问题,因为它是一个Object Array。当然,自Java 1以来就是这样 - 顺便说一句 - 我在这里使用Java 8编译器。
指数4 parseXML [4] = “2015”; 那么我们在这里直接用不可变的String literal 2015
的地址覆盖地址指数5& 6 StringBuffer和MutableInteger正确反映修正,因为它们仍然指向相同的地址。 Java不会创建新副本,因为它们的定义本质上是可变的。
指数7 反映更改,因为它是一个可变的StringBuffer而不是共享的不可变文字!!
指数8 遭受同一个原语被自动装入不可变共享单拷贝文字的问题。
因此,如果您希望存储数组的内容反映数组之外的修改更改,请使用Mutable Objects。并且,要注意自动Autoboxing陷入不可变的Object文字的陷阱。