String str1 = "abc"; String str2 = "abc"; System.out.println(str1 == str2);//true String str3 = new String("abc"); String str4 = new String("abc"); System.out.println(str3 == str4);//false String s1 = "ja"; String s2 = "va"; String s3 = "java"; String s4 = s1 + s2; System.out.println(s3 == s4);//false System.out.println(s3.equals(s4));//true
栈和堆
Java中的内存划分为两种:栈内存,堆内存。
当在一段代码块定义一个变量时,Java救灾栈中为这个变量分配内存空间,当超出变量的作用域后,Java会自动释放掉为变量所分配的内存空间。
堆内存用来存放有new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
栈主要存放一些基本类型的变量和对象句柄。
数据共享
栈有一个很重要的特性,就是数据共享。如:int a = 3; int b = 3; 编译器先处理int a = 3; 会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有,就将3存放进来,然后将a指向3。接着处理int b = 3; 在创建完b的引用变量后,因为在栈中已经由3个值了,便将b直接指向3。这样a与b同时均指向3.
对象引用
String是一个包装类数据。可以:
String str = new String("abc"); String str = "abc";
第一种用new()方法来创建对象的,它会存放在堆中。每调用一次就会创建一个新的对象。而第二种是先在栈中创建一个String类的对象引用变量str,然后查找堆中有没有存放"abc",如果没有,就将"abc"存放在栈中,并令str指向"abc",如果有,则直接指向"abc"。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==。
String str1 = "abc"; String str2 = "abc"; System.out.println(str1 == str2);//true
可以看出str1和str2是指向同一个对象的。
String str3 = new String("abc"); String str4 = new String("abc"); System.out.println(str3 == str4);//false
对于new()的对象则一概在堆中创建新对象,不管其字符串值是否相等,是否有必要创建新对象。
另外,String str1 = "abc"; 创建的对象str,对象可能并没有被创建,而可能只是指向一个先前已经创建的对象。只有通过new方法才能保证每次都创建一个新对象。
自测题:
String bb = "abc"; System.out.println(aa==bb); bb = "a" + "b" + "c"; System.out.println(aa==bb); System.out.println(aa.equals(bb)); String cc = "a"; String dd = cc + "d"; System.out.println(cc.equals(dd));
原文摘自:java内存机制,分析堆和栈的存储特点