【请问】String中的intern方法是不是多余的?

HeBanBei 2016-11-03 05:45:03
api 文档上说:
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。
否则,将此 String 对象添加到池中,并返回此 String 对象的引用。

关键是“否则”这半句。String对象创建的时候不是就已经在常量池中了吗?为什么还要调用这个方法添加一下呢?


Data of types int, long, float, and double, as well as references
to instances of class String, are managed using the ldc, ldc_w, and ldc2_w
instructions.
The ldc and ldc_w instructions are used to access values in the run-time constant
pool (including instances of class String) of types other than double and long.
这一段英文的意思是,String等类型的数据使用 ldc, ldc_w, and ldc2_w指令。而这些指令就是通过常量池访问的。
从这里可以看出,String类型对象的访问是通过常量池的。
也就是说常量池中一定是有String对象的。而与intern 方法是否被调用无关。

那么,intern 方法将对象添加到常量池中的作用有什么意义呢?
...全文
539 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
HeBanBei 2016-11-08
  • 打赏
  • 举报
回复
引用 4 楼 Sun1956 的回复:
[quote=引用 3 楼 abcdefghiijklmnopqrs 的回复:] String str = new StringBuilder("hello").append("world").toString();如果是这样呢? 只有调用str.intern()方法才会在常量池中创建helloworld对象而且只是一个引用和str指向了同一个对象 System.out.println(str.intern() == str);这句话是true
看API,有明确的说明!

When the intern method is invoked, if the pool already contains a string equal to this String object as deterined by the equals(Object) method, then the string from the pool is returned. Otherwise, this string objecct is added to the pool and a reference to this String object is returned.
[/quote] 你引用的这段api文档并不能解除3楼的疑惑。因为我也有同样的疑惑。 对intern函数的用法,我通过api是能理解的。 但是StringBuilder对象的toString方法返回的String对象与new String有何区别呢? 它是在常量区中还是在堆中呢? 另外,5楼的链接中提到不同版本有不同的结果,又是如何理解?
sky_08_06_02 2016-11-08
  • 打赏
  • 举报
回复
HeBanBei 2016-11-08
  • 打赏
  • 举报
回复
http://tech.meituan.com/in_depth_understanding_string_intern.html 问题已解决
HeBanBei 2016-11-08
  • 打赏
  • 举报
回复
引用 8 楼 Sun1956 的回复:
2、JDK >= 1.7时: JDK1.7及以上时,常量池移到Heap中(JDK1.8正式移除PermGen),是一个区域。对于上面的代码,str1还是指向Heap,常量池中此时仍然没有“helloworld”,当调用intern()方法时,发现常量池没有,创建,此时就不同了,由于都是在Heap中,常量池发现Heap中有“helloworld”,就把引用直接指向Heap中的“helloworld”(也就是str1),所以此时str1 == str2
先讨论JDK >= 1.7的情况,我换一种问法: String str1 = new StringBuilder("hello").append("world").toString(); String str3 = new StringBuilder("hello").append("world").toString(); str1 == str3 吗?为什么?这两句涉及多少个String对象?这些对象有什么关系? 同样的问题对以下两句又如何解释? String str1 = new String("aaa"); String str3 = new String("aaa");
ps45221 2016-11-08
  • 打赏
  • 举报
回复
引用 7 楼 HeBanBei 的回复:
[quote=引用 4 楼 Sun1956 的回复:] [quote=引用 3 楼 abcdefghiijklmnopqrs 的回复:] String str = new StringBuilder("hello").append("world").toString();如果是这样呢? 只有调用str.intern()方法才会在常量池中创建helloworld对象而且只是一个引用和str指向了同一个对象 System.out.println(str.intern() == str);这句话是true
看API,有明确的说明!

When the intern method is invoked, if the pool already contains a string equal to this String object as deterined by the equals(Object) method, then the string from the pool is returned. Otherwise, this string objecct is added to the pool and a reference to this String object is returned.
[/quote] 你引用的这段api文档并不能解除3楼的疑惑。因为我也有同样的疑惑。 对intern函数的用法,我通过api是能理解的。 但是StringBuilder对象的toString方法返回的String对象与new String有何区别呢? 它是在常量区中还是在堆中呢? 另外,5楼的链接中提到不同版本有不同的结果,又是如何理解? [/quote] Ok,详细说明下好了,这个方法比较蛋疼! 确实不同版本的jdk是有区别的,大致分为2种。

String str1 = new StringBuilder("hello").append("world").toString();
String str2 = str1.intern();
System.out.println(str1 == str2);
1、JDK <= 1.6时: JDK1.6及以下时,常量池(好像叫PermGen)是不再Heap上的,是两个不同的区域。对于上面的代码,str1指向Heap,常量池中没有“helloworld”,当调用intern()方法时,发现常量池中没有,就创建一个,并返回该引用(指向常量池的),所以此时str1 != str2。 2、JDK >= 1.7时: JDK1.7及以上时,常量池移到Heap中(JDK1.8正式移除PermGen),是一个区域。对于上面的代码,str1还是指向Heap,常量池中此时仍然没有“helloworld”,当调用intern()方法时,发现常量池没有,创建,此时就不同了,由于都是在Heap中,常量池发现Heap中有“helloworld”,就把引用直接指向Heap中的“helloworld”(也就是str1),所以此时str1 == str2
ps45221 2016-11-07
  • 打赏
  • 举报
回复
引用 3 楼 abcdefghiijklmnopqrs 的回复:
String str = new StringBuilder("hello").append("world").toString();如果是这样呢? 只有调用str.intern()方法才会在常量池中创建helloworld对象而且只是一个引用和str指向了同一个对象 System.out.println(str.intern() == str);这句话是true
看API,有明确的说明!

When the intern method is invoked, if the pool already contains a string equal to this String object as deterined by the equals(Object) method, then the string from the pool is returned. Otherwise, this string objecct is added to the pool and a reference to this String object is returned.
shikebing 2016-11-07
  • 打赏
  • 举报
回复
不是多余的,但是得慎用。我之前在夜眸博客总结过一篇文章,建议你看看 http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt399
  • 打赏
  • 举报
回复
String str = new StringBuilder("hello").append("world").toString();如果是这样呢? 只有调用str.intern()方法才会在常量池中创建helloworld对象而且只是一个引用和str指向了同一个对象 System.out.println(str.intern() == str);这句话是true
ps45221 2016-11-04
  • 打赏
  • 举报
回复
还是有点不同的,对于String str = "hello";这种方式声明的字符串,这时候str的引用地址是指向常量池的。 而String str = new String("hello");这种new出来的,这时候str的引用地址是指向堆内存的String对象的,然后堆内存中string对像中有个char数组,是指向常量池的。 最后String中intern()方法,你也看过API了,它是返回常量池的引用,所以new出来的string(此时它的引用是指向堆内存上的string对象),此时调用intern方法,是返回常量池中的引用。

String a = "hello";
String b = new String("hello");
System.out.println(a == b.intern());  // 输出true
System.out.println(a == b);               // 输出false
System.out.println(a == b.intern());  // 输出false
ps45221 2016-11-04
  • 打赏
  • 举报
回复
引用 1 楼 Sun1956 的回复:
还是有点不同的,对于String str = "hello";这种方式声明的字符串,这时候str的引用地址是指向常量池的。 而String str = new String("hello");这种new出来的,这时候str的引用地址是指向堆内存的String对象的,然后堆内存中string对像中有个char数组,是指向常量池的。 最后String中intern()方法,你也看过API了,它是返回常量池的引用,所以new出来的string(此时它的引用是指向堆内存上的string对象),此时调用intern方法,是返回常量池中的引用。

String a = "hello";
String b = new String("hello");
System.out.println(a == b.intern());  // 输出true
System.out.println(a == b);               // 输出false
System.out.println(a == b.intern());  // 输出false
写错了,第5行应该是b == b.intern()
System.out.println(b == b.intern());  // 输出false

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧