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软件工程师的基础知识点

原文摘自:java内存机制,分析堆和栈的存储特点