日期:2014-05-20  浏览次数:20611 次

数组在内存中的分析(需要专业回答)
public class TestArray {
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false;
System.out.println(a1[2]==a2[2]); //true; 请用内存解析为什么是true!
a1[1] = new String("hello"); 
a2[1] = new String("hello"); 
System.out.println(a1[1] == a2[1]); //false; 请用内存解析 为什么是false;  
//并对照上面的true,说出区别!

a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // true; 对照所有的解析,说出地址分析区别!
}
}
/* 提问:  A a[] = new A [a.length];
1.定义一个数组a是new出来的, 里面分配了a.length个空间吗?. 
2.这些空间有没有各自的地址以区分他们?例如前驱,后继!
3.== 号是不是地址和值两项的比较?
4.==号是不是只有两项全为true时,才为true?
5. a[i] 代表什么,是代表了值,还是地址,还是代表了两项?
6. 如果a[i] 只代表了一项,那另一项是靠什么来区分?.  
7.a[i] == a[j] ; 为true时;  有没有比较他们的地址?,
如果没有! 请说出为什么?
8.综合上述 说出 引用,指针,地址,变量,内存解析和区别!
*/

------解决方案--------------------

栈空间有地址和空间, 堆里也有地址和空间!~ 
很明显: 
int[] a, b;
a = new int[100];
很明显,这经过了赋值运算的一个过程! 
----------
楼主一直都是在陈述,一个问句都没有,何惑之有?

提醒楼主多次了,不要用地址这个概念来考虑问题,用引用,这个是java里明确给出的概念。当然,引用最终是靠地址来实现的,但从概念上来说,我们把这个地址叫做引用。但从另一个角度想,目前的计算机需要用地址来表示引用,如果有另外一个体系结构的计算机,我可以完全不用地址而一样能表示引用。所以说,地址是与jvm实现相关的,而引用则是java语言自身的概念,独立于jvm。

声明变量的作用是什么? >.
1.识别! 
2.分配空间! 
----------
你的这两句说的没错,变量说白了就是个“助记符”!没有什么特殊意义。我所强调的是:对于primary类型的来说,变量里面存的是值;对于Object的子类(包括Object本身)来说,变量里存的是引用。我并不care变量本身的在哪里,是在堆还是在栈都没关系,我care的是变量里存的东西。

new int[100] 结果是在堆上生成一个int数组的存储空间,这个空间可以存放100个int类型的值,并且缺省的,这些值都是0。如果改为 new String[100],则结果在堆上生成一个String数组的存储空间,这个空间可以存放100个String类型对象的引用,并且缺省的,这些引用都是null。这里是对数组的初始化,是java规范里要求的,不应该理解为普通意义上的赋值,因为并没有调用赋值操作。

1个int需要4个字节来保存,但new int[100]并不是仅仅生成100*4个字节,还需要为管理这些内存多申请一小块(内存头),具体多大取决于虚拟机实现,用于对这100*4个字节的管理。这也是对楼顶所问的数组的length是怎么得到的一个回答。同时,我也想说明,如果一个变量引用了这个数组,这个引用所代表的地址是指到第一个数组元素所在的地址,还是指到为内存头所在的地址,是和jvm实现相关的。甚至于内存头和其所对应的内存块是连续存放的,还是不连续存放的,也是与jvm实现相关的,java语言并不care这个。用引用这个概念,我可以屏蔽这些差异,而用地址,则太底层了,无法屏蔽。


------解决方案--------------------
int []a

//你自己对照第二个去理解吧。这里只是声明了一个变量叫a,其值是一个元素为int的数组,
或者说a引用了一个元素为int的数组。这个数组和a是两回事!假如代码如下: 

你这句话说的是对的! 声明了一个变量a , 
并在栈空间里分配了为int类型变量足够的空间!
这个是我的补充!~不对,stack中只为a分配了空间,这个a可以指向一个数组(里面存int),但现在这个数组还没有分配空间,所以a指向null,将来给数组分配空间也是在heap中分配,因为数组不是primitive类型。

再补充查到的一个知识点: 
变量名是不可变的, 也就是说它的地址是唯一的,分配了不可再改变!不对,例如:
Dog d1 = new Dog();
Dog d2 = new Dog();
d1 = d2; //d1的指向已经变了,现在指向后来创建的那个对象了

因为变量是有生命周期的,出了大括号就不存在了,所以它的地址是在栈里的!
出栈就消失了!~
它的值究竟在不在栈里呢? > 不太清楚, 估计基本数据类型是在栈里的!
变量在stack中还是在heap中,要看变量是 实例变量(instance variable)还是局部变量(local variable)
instance variable 在heap中, local variable 在stack中
实际上,stack中是按method出入stack的,先调用的method在下面,然后再调用的method在上边,最上边的method是当前运行的methed,local variable就分配在这个methed所占的空间中,当然也是在stack中了。当前的method运行完,弹出stack,这个method里面声明的变量也一起消失了。程序返回到stack中的下一个method继续运行。


所以基本数据类型==是比较值!
int a1 = 3; int a2 = 4; //a1和a2里面存的就是3和4本身。
Dog d1 = new Dog(); Dog d2 = new Dog(); //d1和d2里面分别存这两个独享的引用,这两个引用显然不同,比较结果就是false了。

不知道你可否还能为 这句话 再做补充,因为"[]" 并没有解释到~!~


第三个:
int[] a, b; 
a = new int[100]; 

//new 的 地址 肯定是在堆里了, 这点大家都不怀疑!
这个时候 变量a 的地址是不可变的!~ 好,抛开地址不谈, 
我们谈空间, 这个小块内存肯定是在堆里了!~ 

到这里你看出点疑惑了吗?.. 请您把这里解释通!~~

a在 stack中, new int[100]这个数组对象在heap中。

建议楼主看下《head first in java》,里面说的非常清楚。