(Java基础)关于String.intern()方法

1 需要了解创建字符串的方式

1 是直接 String s1 = new String(" abc");

这个方式创建的字符串,s1指向的是一个堆上的实例的地址,但是与此同时也会在常量池当中创建出一个abc的字符串.
以这种方式创建字符串,每一个变量指向的地址是不同的,因为每次都指向一个堆上的新的地址。但是常量池中却只有一个abc这样的常量

String s1 = new String("abc");
String s2 = new String("abc");
System.out.print(s1 == s2);//false

2 是用 String s1 = “abc”;

这个方式创建的s1指向的是一个常量池中字符串的地址。
直接以这种方式创建字符串,首先会在常量池当中查找是否有相同的字符串,如果存在的话则返回的是在常量池的地址。所以这也就解释了下面的原因。

	String s1 = "abc";
	String s2 = "abc";
	System.out.println(s1==s2);//true;

2 对于intern的用法的说明。

String.intern()
在JDK1.6中是会把首次遇到的字符串复制到常量池当中,返回的也是在常量池中的字符串的地址。
在JDK1.7以后,不会复制字符串到常量池而是把字符串的实例(首次出现)地址复制到常量池当中,返回的是常量池当中的引用,即返回的是堆中第一次出现该实例的地址。
即1.6返回的常量池的地址,而1.7以后返回的是堆上的地址。

3 对于字符串的拼接的问题

1 第一种方式,拼接的都是字面量的加法即"JA"+“VA”

String s1 = "JA"+"VA";

这样创建的 s1会直接去常量池中寻找是否存在"JAVA"的样式,如果有则返回,如果没有则在常量池中创建一个。

2 第二种方式,通过引用对象及str2+str3

String s1 = s2 + s3;

这样与第一种方式生成的字符串是不相同,这个是通过StringBuilder.append()方式实现的新的对象,这是创建在堆上的对象,s1指向的是堆上的地址。

4 方便理解的几个例子

String str2 = new String("str")+new String("01");
str2.intern();
String str1 = "str01";
System.out.println(str2==str1);//true

当使用 str2.intern()的时候,发现常量池中并没有"str01"这样的字符串。所以会在常量池创建出一个这样的对堆上内存的引用。
当str1再去创建"str01"这样的对象的时候,发现常量池中存在了这样的对象引用。所以这两个都是指向堆上内存的引用。
所以输出结果是true.

String str2 = new String("str")+new String("01");
String str1 = "str01";
str2.intern();
System.out.println(str2==str1);//false

下面这个调换位置以后输出为false,原因是因为由于是字符串拼接而成的,所以str2指向的是堆上的内存地址,而在常量池中并不会存在这样的内容。
所以当创建str1时候会搜索常量池,发现没有这样对象便在常量池中创一个一个"str01",所以str1返回的是常量池中的地址,str2.intern()发现存在了(“”str01”)所以会返回一个如果存在,则返回常量池中的引用。
但是str2指向的是堆上的地址。所以是false.

这里存在着一个问题:

		String str2 = new StringBuilder("str").toString();
		str2.intern();
		String str1 = "str";
		System.out.println(str1 == str2);//false

这个与第一个类似,但是注意的是这是用new直接创建的而不是通过拼接得到的。所以这个时候在常量池中已经存在了"str"。
str2.intern()也不会像第一个一样创建出一个对于堆上内容的引用。
所以str2指向的堆,str1指向的是常量池。所以结果为false.

扩展 当存在final的时候。编译期直接进行了常量替换(而对于非final字段则是在运行期进行赋值处理的)。

String s1 = “abc”; 
final String s2 = “a”; 
final String s3 = “bc”; 
String s4 = s2 + s3; 
System.out.println(s1 == s4); 
A:true,因为final变量在编译后会直接替换成对应的值,所以实际上等于s4=”a”+”bc”,而这种情况下,编译器会直接合并为s4=”abc”,所以最终s1==s4。

文章参考 https://blog.csdn.net/soonfly/article/details/70147205#commentBox

猜你喜欢

转载自blog.csdn.net/weixin_43872339/article/details/87457127