关于 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 ...
随机推荐
- 一步一步学Vue(十二)
为了提升代码的逼格,之后代码改为Vue文件组件,之前代码虽然读起来容易理解,而且适合在小的项目中使用,但是有如下缺点: 全局定义(Global definitions) 强制要求每个 componen ...
- 读书笔记(一)—— 浅析浏览器渲染过程和html中的文件加载
在构建页面时,我们会在html中载入一个或多个css和js文件.或许大家都已经习惯了"最佳实践"中,css文件应该放在<head>标签中引入,而js文件则是放在< ...
- NYOJ--325--深度优先搜索--zb的生日
/* Name: NYOJ--325--zb的生日 Author: shen_渊 Date: 15/04/17 08:18 Description: 输入时计算总质量,DFS搜索和总质量差值一般最接近 ...
- IntelliJ IDEA(2017.2)安装和破解(转)
如果有一定的经济基础,请支持正版,这里提供破解方法. 一.下载并安装, IntelliJ IDEA的官网:https://www.jetbrains.com 二.破解. 百度下载一个 Jetbrain ...
- 关于Wifi室内定位应用中的一些问题:
公司目前在办公室内布设了一套室内定位的实验环境,用的是华为路由器,采用的算法是基于信号强度的RSSI算法.公司目前希望能使用这套设备得到无线网络覆盖范围下的所有移动设备(对应每个人)的MAC地址,同时 ...
- iPhone 尺寸
http://tool.lanrentuku.com/guifan/ui.html 这是本人复制的链接,,
- 扩展Python模块系列(二)----一个简单的例子
本节使用一个简单的例子引出Python C/C++ API的详细使用方法.针对的是CPython的解释器. 目标:创建一个Python内建模块test,提供一个功能函数distance, 计算空间中两 ...
- 从零入手微信小程序开发
前言: 哈哈,发现我写的随笔都是项目驱使的.当然,这篇也是项目驱使的咯,前段时间领导在玩微信时候发现了微信小程序的好处,流程,切换速度快等,然后就让小弟研究研究小程序的实现. 补充下,博客大多都是处理 ...
- Linux/Unix监控其他用户和信号
--Linux/Unix监控其他用户和信号 ------------------------------------------------------2013/10/27 查看有哪些用户登录 w ...
- css盒子边框样式
边框样式有全边框和单个边框样式,可对每条边设置不同的样式 如下代码P1为全边框样式,P2为单个边框设置不同的样式: <!DOCTYPE html> <html lang=" ...