本文针对Java中String类的易混淆的相关问题进行记录
一、问题1
1.问题
public static void main(String[] args) {
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s == s1);
System.out.println(s == s2);
System.out.println(s1 == s2);
System.out.println(s == s.intern());
System.out.println(s1 == s1.intern());
System.out.println(s.intern() == s2.intern());
}
- 上述代码中,前三行会在内存中创建几个对象?后面每一行的输出?
2.分析
- 通过上面的分析,想必字符串对象的创建问题已经很清楚了
- 下面分析后面的几个判断问题
System.out.println(s == s1);
- s指向堆中的地址,s1指向
String Pool
,显然不等,所以false
- s指向堆中的地址,s1指向
System.out.println(s == s2);
false
System.out.println(s1 == s2);
false
- 关于
intern()
方法的详解请参考这篇文章 - 这里只需要知道任何一个字符串只要调用了
.intern()
方法都会去String Pool
中查找该字符串是否存在,如果存在,则返回该字符串在String Pool
的地址 - 如果不存在,则会在
String Pool
中创建该字符串,然后返回地址 - 那么关于下面的判断应也很简单了:
// s.intern()返回的是 Sting Pool中的地址 s是指向堆中的地址 显然不等
System.out.println(s == s.intern());//false
// s1指向 String Pool中"abc"的地址 s1.intern刚好也返回该地址
System.out.println(s1 == s1.intern());//true
// 这两个地址一样 都是指向String Pool中的abc
System.out.println(s.intern() == s2.intern());//true
3.String创建对象小结
- 这里关于字符串对象创建有几点值得总结的:
- 不管是
String s = new String("xx")
还是String s = "xxx"
都会先在String Pool
中查找想要创建的字符串是否已经存在。如果存在,则都不会再在String Pool
中创建对象。 - 区别在于
new
的方式还会在堆中创建一个对象 - 后一种方式直接把在
Sting Pool
中对象地址返回给s
- 不管是
- 所以,
new String
的方式至少在堆中创建一个对象,可能在Sting Pool
中再创建一个对象 String = ""
的方式至多在String Pool
中创建一个对象,也有可能不创建对象
二、问题2
1.问题
public static void main(String[] args) {
String hello = "hello";
String hel = "hel";
String lo = "lo";
System.out.println(hello == "hel" + "lo" );
System.out.println(hello == "hel" + lo);
}
- 问上述输出结果
2.分析
public static void main(String[] args) {
String hello = "hello";
String hel = "hel";
String lo = "lo";
// “hel” + "lo"两个都是字面值(常量) 相加,加到一起后,会去常量池中查看是否存在该字符串
//如果存在则返回常量池中的地址,那么这里就是true
System.out.println(hello == "hel" + "lo" );
//当一个字面值 + 变量 会在堆中创建一个新对象,所以false
System.out.println(hello == "hel" + lo);
}