关于 String.intern() 的思考
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt399
我看到一个问题 https://segmentfault.com/q/10... 是关于 String.intern() 的, 感觉比较有意思, 于是自己也去探索了一下, 有了一些自己的见解, 于是在此记录下来.
我们首先来看一个例子:
// 1
String str1 = new StringBuilder("ja").append("va").toString();
System.out.println(str1.intern() == str1);
// 2
String str2 = new StringBuffer("编").append("程").toString();
System.out.println(str2.intern() == str2);
// 3
String str3 = new StringBuffer("编").append("程").toString();
System.out.println(str3.intern() == str3);
这个例子会输出什么呢? 有些读者朋友可能没有想到, 其实上面的例子在不同的 JDK 版本中运行, 会有不同的结果的. 那么接下来我们来试一下吧:
// 使用 JDK6 进行编译运行:false, false, false
// 使用 JDK7 进行编译运行:false, true, false
为什么结果会不同呢?首先我们来看一下第一部分:
String str1 = new StringBuilder("ja").append("va").toString();
System.out.println(str1.intern() == str1);
这里 JDK6 和 JDK7 都是打印的 false, 其原因是 "java" 字符串常量比较特殊, 它是固定存在字符串常量池中的, 因此 "str1.intern()" 返回的就是字符串常量池中的对象的引用, 和堆上的 str1 就自然是不相等了.
接下来我们来分析一下第二部分的代码:
// 2
String str2 = new StringBuffer("编").append("程").toString();
System.out.println(str2.intern() == str2);
在这里 JDK6 和 JDK7 的输出有了差异, 其具体原因是 JDK6 和 JDK7 对 String.intern() 方法的实现的不同.在 JDK6 及以前的 JDK 中:
intern() 方法会把首次遇到的字符串实例 **复制** 到永久代中, 然后返回永久代中的实例.
而对于 JDK7 以及之上的JDK:
当遇到第一次出现的字符串时, intern() **不再复制实例**, 而是在常量池中记录首次出现的实例的引用, 并且 intern() 返回的是此实例引用.
根据 JDK6 和 JDK7 的 intern() 方法的区别, 我们就知道了在第二部分的代码中, "编程" 这个字符串是第一次出现的, 因此在 JDK6 中, 会将此对象的实例拷贝一份然后存放到常量池中, intern() 返回的是在常量池中拷贝后的新对象的引用, 进而就和堆上的 str1 不等了; 而在 JDK7 中, 由于 intern() 方法的实现不同, 这个方法并不会拷贝一份对象实例到常量池中, 而是在常量池中记录此对象的引用, 因此 intern() 返回的引用其实和堆中的 str1 是一样的.
有了前面的认知, 我们对第三部分的代码的输出结果就比较熟悉了:
// 3
String str3 = new StringBuffer("编").append("程").toString();
System.out.println(str3.intern() == str3);
第三部分代码和第二部分代码其实是一样的, "编程" 这个字符串已经在第二部分的代码中出现了, 因此在常量池中已经存在了, 因此 str3.intern() 返回的是常量池中的对象的引用, 和堆上的 str3 自然是不一样的, 因此不论在 JDK6 还是 JDK7 中, 输出的都是 false.
关于 String.intern() 的思考的更多相关文章
- C#的字符串优化-String.Intern、IsInterned
		
https://www.jianshu.com/p/af6eb8d3d4bf 首先看一段程序: using System; class Program { static void Main(strin ...
 - Java提高篇——理解String 及 String.intern() 在实际中的应用
		
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ...
 - 深入理解Java String#intern() 内存模型
		
原文出处: codelog.me 大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 字符串 ...
 - 常量池之String.intern()方法
		
JDK7将String常量池从Perm区移动到了Java Heap区.在JDK1.6中,intern方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中的实例.但是在JDK1.7以后,Str ...
 - String放入运行时常量池的时机与String.intern()方法解惑
		
运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...
 - 字符串常量池和String.intern()方法在jdk1.6、1.7、1.8中的变化
		
字符串常量池也是运行时常量池 jdk1.6中,它是在方法区中,属于“永久代” jdk1.7中,它被移除方法区,放在java堆中 jdk1.8中,取消了“永久代”,将常量池放在元空间,与堆独立了 pub ...
 - string.intern
		
在翻<深入理解Java虚拟机>的书时,又看到了2-7的 String.intern()返回引用的测试. 总结一句话: jdk1.7之前,调用intern()方法会判断常量池是否有该字符串, ...
 - 运行时常量池中的符号引用/String.intern() /ldc指令
		
运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中. 具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象 ...
 - synchronized (string.intern())
		
在jdk7下慎用String.intern()作为synchronized的对象锁: https://www.cnblogs.com/yhlx/p/3498387.html String.intern ...
 
随机推荐
- mysql 5.7 root密码重置(centos 7)
			
mysql5.7版本之后,与mariadb不同,在安装之后,在启动之时,会进行自动随机密码的设定,所以在systemctl start mysqld之后,会出现mysql -uroot -p无法登陆的 ...
 - gitlab 实现自动部署(简单Python实现)
			
功能说明: 当本地master分支执行push动作的时候,服务器端会自动执行master分支的pull操作(还可以执行一些自动化脚本) 原理: git hooks就是那些在git执行特定事件(如com ...
 - appium测试之获取appPackage和appActivity
			
appPackage和appActivity 进行appium自动化测试非常重要的两个参数,我们所测试的APP不同,这两个参数肯定也是不一样的.那如何快速的获取这APP的这两个参数呢?我这里介绍两个方 ...
 - NO.1-M2
			
一,CSS盒模型 1,当父盒子包裹子盒子,且上边线重合时,给子盒子添加margin-top时,子盒子与父盒子的上边线并不能分开,,而是导致,两个盒子同时下来,而是导致,两个盒子同时下来 使两条上边 ...
 - 7种方法解决移动端Retina屏幕1px边框问题
			
在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样 ...
 - insertBefore  和   insetAfter函数详解
			
在Javascript DOM编程艺术上面讲到,insertBefore( )函数,即在已有元素前面插入一个新元素: 语法: parentElement . insertBefore(newEle ...
 - 关于浏览器解析html全过程详解
			
本人web前端菜鸟一枚,第一次在这里发博客梳理知识,知识都是从各地方查阅引用以及自己的理解得来,有什么错误的地方欢迎指正. DOM文档通常加载的步骤: 1.解析HTML结构. 2.加载外部脚本和样式表 ...
 - Java字符串操作
			
最近翻看之前的东西,发现有些看似简单的东西竟然忘的差不多了,记录一下对字符串大小写转换的操作. 打印结果
 - C++生成dump文件
			
C++代码中,使用DbgHelp模块的MINIDUMP编程生成 #include "DbgHelp.h" typedef BOOL (WINAPI* MINIDUMPWRITEDU ...
 - centos 7.2 配置Nginx
			
1.添加资源 添加CentOS 7 Nginx yum资源库,打开终端,使用以下命令(没有换行): rpm -Uvh http://nginx.org/packages/centos/7/noarch ...