概念

对于基本数据类型,== 比较的是
对于对象类型,== 比较的是对象的地址

特殊(String)

// 例一
String str = "wo";
String str1 = "wo";
System.out.println("例一:" + (str == str1));

// 例二
String str2 = new String("wo");
String str3 = new String("wo");
System.out.println("例二:" + (str2 == str3));

//结果
//例一:true
//例二:false

从上面的结果可以看到,String不是对象类型么?为什么例一是true呢?
这个涉及到字符串常量池的概念。

字符串常量池

概念

String类是我们平常项目中使用频率非常高的一种对象类型,JVM为了提升性能和减少开销,避免字符串的重复创建,维护了一块特殊的内存空间,即字符串常量池。

变化

在JDK1.6及之前版本,字符串常量池在方法区中。
在JDK1.7及以后版本,字符串常量池移到了堆中。

原理

使用String str=“wo”,可能创建一个或者不创建对象。
如果“wo”在字符串常量池中已经存在,则不会再创建String类型的值为“wo”的对象,而是将str指向这个“wo”对象内存地址,后续无论用这种方式创建多少个指向“wo”的引用,在内存中,都只有一个“wo”内存地址被分配。

图解

String str = "wo";
image.png
String str = new String("wo");
image.png

结论

通过上面的分析,我们可以知道例一为何true,例二为何false的原因。

String str = new String("wo")创建了几个对象?

如果字符串常量池中没有"wo",则该句创建了两个对象。
首先会创建一个"wo"存放在字符串常量池中,其本身就是一个对象;然后会new 一个字符串对象,并将"wo"的引用返回给new出来的对象。

如果字符串常量池中有"wo",则该句只创建了一个对象,因为该句首先会查找字符串常量池中是否存在"wo",如果存在则直接返回"wo"的引用给new出来的对象。