关于 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 ...
随机推荐
- [补档]happiness
happiness 题目 传送门:http://cogs.pro/cogs/problem/problem.php?pid=1873 高一一班的座位表是个n×m的矩阵,经过一个学期的相处,每个同学和前 ...
- hdu 6047 Maximum Sequence(贪心)
Description Steph is extremely obsessed with "sequence problems" that are usually seen on ...
- HDU5744 Keep On Movin (思维题,水题)
Problem Description Professor Zhang has kinds of characters and the quantity of the i-th character i ...
- python--DenyHttp项目(2)--ACM监考客户端1.0版
修复了: 360搜索可以使用的漏洞 更新版本,上一版本复制的Hosts文件保留的漏洞 #coding:gbk import os import sys from subprocess import * ...
- Java Socket 编程
1. 背景 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. java.net 包中 J2SE 的 API 包含有类和接口,它们提供低层次的通信细节.你可以直接使用这些类和 ...
- 安徽省2016“京胜杯”程序设计大赛_H_单身晚会
单身晚会 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 53 Accepted: 16 Description ZJ和Z ...
- Centos 7.3 安装mysql5.7.19 各种调试就不多说了
mysql 5.7.19linux-glibc2.12 (x86_64) 安装 1.在安装目录进行解压2.mv解压目录为mysql3.创建mysql的用户 useradd -s /sbin/nolon ...
- JavaScript中的EcMAScript学习笔记
一.Javascript概述(知道) a.一种基于对象和事件驱动的脚本语言 b.作用: 给页面添加动态效果 c.历史: 原名叫做livescript.W3c组织开发的标准叫ECMAs ...
- TestNG的组测试和组中组测试
在编写测试的过程中,我们经常遇到只想执行个别或者某一部分/某一类型的测试用例,这时我们可以使用TestNG的分组测试方法 分组测试在配置时,TestNG执行的原则是:只保留最小集合进行执行 看代码: ...
- KMS注册
--KMS注册 -------------2014/03/25 --Read this First http://social.technet.microsoft.com/wiki/contents/ ...