String.intern()使用总结

1. 知识点一

1
2
3
String s = new String("1");
String s1 = s.intern();
System.out.println(s == s1); //输出结果为: false

对于new String("1")会生成两个对象,一个是String类型的对象,它将存储在Java Heap中,另一个字符串常量对象1,它将存储在字符串常量池中、。
s.inertn()方法会先去字符串常量池中查找是否存在字符串常量1,如果存在则返回该对象的地址,如果不存在则在字符串常量池中生成一个1字符串常量,并返回该对象的地址。

如下图:

变量s指向的是String类型对象,变量s1对象指向的是”1”字符串常量对象,所以 s ==s1结果为false。

2. 知识点二

在上面的基础上再定一个s2,如下:

1
2
3
4
5
String s = new String("1");
String s1 = s.intern();
String s2 = "1";
System.out.println(s == s1); //false
System.out.println(s1 == s2); //true

s1 == s2 为true,表示变量s2是直接指向的字符串常量,如下图所示:

3. 知识点三

1
2
3
4
String s = new String("1");
String t = new String("1");
System.out.println(s == t); //false
System.out.println(s.intern() == t.intern()); //true

s == t为false,这个很明显,变量s 和变量t 指向的是不同的两个String类型的对象。

s.intern() == t.intern()为true,因为intern()方法返回的是字符串常量池中的同一个对象1,所以为true

4. 知识点四

1
2
3
4
String x = new String("1") + new String("1");
String s3 = "11";
System.out.println(x == s3); //false
System.out.println(x.intern() == s3.intern()); //true

变量x为两个String类型对象相加,那x依旧还是一个String类型对象,所以x != s3;调用x.intern()方法将返回11对应的字符串常量,所以x.intern() == s3.intern()为true

5. 知识点五

1
2
3
4
5
6
7
8
String x = new String("1") + new String("1");
String x1 = "1" + new String("1");
String x2 = "1" + "1";
String s3 = "11";

System.out.println(x == s3); //false
System.out.println(x1 == s3); //false
System.out.println(x2 == s3); //true

x == s3为false,表示x指向String类型对象, s3指向字符串常量;

x1 == s3为false,表示x1指向String类型对象, s3指向字符串常量;

x2 == s3为true,表示x2指向字符串常量, s3指向字符串常量;

所以可以看到new String("1") + "1"返回的是String类型的对象

6. 总结

现在我们知道intern()方法就是将字符串保存到常量池中,在保存字符串到常量池的过程中会先查看常量池中是否已经存在相等的字符串,如果存在则直接使用该字符串。

所以我们在写业务代码的时候,应该尽量使用字符串常量中的字符串,比如使用String s = "1" 比使用 new String("1")更节省内存;

我们也可以使用String s = String类型对象.intern()方法来间接使用字符串常量。 这种做法通常用在你接收到一个String类型的对象而又想节省内存的情况下,当然你完全可以
String s = String类型对象,但是这么用可能会因为变量s的引用而影响String类型对象的垃圾回收,所以我们可以使用intern方法进行优化,但是需要注意的是intern能节省
内存,但是会影响运行速度,因为该方法需要求常量池中查询是否存在某个字符串。