栈内存: 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 栈内存主要存放的是基本类型类型的数据 如、( int, short, long, byte, float, double, boolean, char) 和对象句柄。并没有有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、、栈数据可以共享、缺点是数据固定、不够灵活。 栈的共享: String a = "abc"; String b = "abc"; System.out.println(a==b); 结果为true 这就说明了a b其实指向同一个值 注意,我们这里并不用a.equals(b);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,a与b是否都指向了同一个对象。 结果说明,JVM创建了两个引用a和b,但只创建了一个对象,而且两个引用都指向了这个对象。 首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有abc这个值,如果没找到,就将abc存放进来,然后将a指向abc。接着处理String b = "abc";在创建完b的引用变量后,因为在栈中已经有abc这个值,便将b直接指向abc。这样,就出现了a与b同时指向abc 特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=abcd;那么,b不会等于abcd,还是等于abc。在编译器内部,遇到a= abcd;时,它就会重新搜索栈中是否有abcd的字面值,如果没有,重新开辟地址存放abcd的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。 堆内存: 堆内存用来存放所有new 创建的对象和 数组的数据、 String a = new String ("abc"); String b = "abc"; System.out.println(a==b); //False String a = new String ("abc"); String b = new String ("abc"); System.out.println(a==b); //False 创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
原文出自: