解读String的intern()
intern()在面试中也是经常遇到的,本文从案例以及debug来主要讲解intern()。这一块也是困扰本人很久的一个问题,通过debug,查看字节码分析intern()的作用,希望对大家有所帮助。
首先记住intern()的作用:
如果SCP(字符串常量池)中存在与A内容一样的字符串对象C时,就返回C 的地址;
否则将A放入SCP中,返回A的地址。
案例1:
public class StringInternDemo {public static void main(String[] args) {String s1 = new StringBuilder("re").append("dis").toString(); // @479 堆对象String s4 = new StringBuilder("re").append("dis").toString(); // @481 堆对象
// String s5 = "redis"; // @433,放回常量中,首次出现在常量池
// System.out.println(s1 == s5);// 一个是常量一个是堆对象System.out.println(s1.intern()==s4.intern()); // 都想去常量池找,发现已经有了,直接返回@433
// System.out.println(s1.intern() == s5);System.out.println(s1);System.out.println(s1.intern());System.out.println(s1 == s1.intern()); // s1是堆地址,s1.intern()去常量池找,发现已经有了s5,所以s1.intern()指向s5了,返回的是s5的地址。// 假如没有s5,常量池没有,就会吧s1放进常量池,返回s1的地址}
}
debug查看对象地址:
结果:
true
redis
redis
true
分析:
首先只有用双引号(“”)创建的的String才是常量,其他的方式都是新增一个堆对象,所以s1与s4式不同对象,看到堆地址也是不一样的;
s1.intern(),s4.intern(),按照上面intern()的作用都想去常量池找,都没有,s1.intern()先执行,所以会把s1放进常量池,地址为s1的的堆地址,当s4.intern()访问时,发现常量有了(s1放进去的)
所以直接返回s1.intern()存的地址,两个时相等的。
同样s1.intern() = s1的时候,常量池存放的地址就是s1存进去的,必然相等。
以上验证了可能看起来不太直观,那么我们继续新建一个字符串,也就是把上面注释的代码放开,直接放入常量池
String s1 = new StringBuilder("re").append("dis").toString(); // @479 堆对象String s4 = new StringBuilder("re").append("dis").toString(); // @481 堆对象String s5 = "redis"; // @433,放回常量中,首次出现在常量池System.out.println(s1 == s5);// 一个是常量一个是堆对象System.out.println(s1.intern()==s4.intern()); // 都想去常量池找,发现已经有了,直接返回@433System.out.println(s1.intern() == s5);System.out.println(s1);System.out.println(s1.intern());System.out.println(s1 == s1.intern()); // s1是堆地址,s1.intern()去常量池找,发现已经有了s5,所以s1.intern()指向s5了,返回的是s5的地址。// 假如没有s5,常量池没有,就会吧s1放进常量池,返回s1的地址
结果:
false
true
true
redis
redis
false
debug观察;
可以发现s1.intern()的地址是常量s5的,这就相当于,String s5 = "redis";这样创建时直接把s5放入常量池中。
总结:记住上面作用的定义。
小插曲:
其实jdk本身也是自己自带了常量池字符串,可以看Version这个类:
有的jdk8还有保留Java这个字符串
深入jvm虚拟机一书中也提出了:
以下代码也可以验证,发现我们自己没有像上面”redis“新建一个字符串常量,但发现s2 == s2.intern()为false,所以在此之前常量池肯定是有的
String s2 = new StringBuilder("open").append("jdk").toString();String s22 = new StringBuilder("open").append("jdk").toString();System.out.println(s2.intern()==s22.intern());System.out.println(s2);System.out.println(s2.intern());System.out.println(s2 == s2.intern());
------------------
注意:大家应该有发现以上比较的是利用append拼接的,接下来看一下没有用append拼接直接new String或者new StringBuilder
使用new String或者new StringBuilder都是至多创建两个对象
String s3 = new StringBuilder("redis").toString();System.out.println(s3 == s3.intern());
结果是false
debug:
很明显两个是不同的地址
看一下字节码:
发现创建了两个对象,会吧redis这个字符串放入常量池,显示intern的时候,常量池已经有了
比较append拼接:
String s33 = new StringBuilder("red").append("is").toString();System.out.println(s33 == s33.intern());
debug:
显然是通过地址
查看字节码:
发现创建三个对象,但是并没有字符串“redis”,所以intern的时候,会吧redis放入常量池
解读String的intern()相关推荐
- 运行时常量池_从String的intern()到常量池
前言 在知乎上遇到一个刚学Java就接触的字符串比较的问题: 通常,根据"==比较的是地址,equals比较的是值"介个定理就能得到结果.但是String有些特殊,通过new St ...
- String中intern的方法
原文地址:http://www.cnblogs.com/wanlipeng/archive/2010/10/21/1857513.html String中intern的方法 首先查看官方API那个的解 ...
- 字符斜杠是合法常量吗_【面试秘籍】你对String的intern方法了解吗
我们先来看个例子: public class StringTest { public static void main(String[] args) { String a = "A" ...
- Java中String类intern()详解
1.背景 在开发过程中很多朋友,由于不会正确使用intern(),导致开发的程序,执行效率比较差.同时最近发现一道非常有意思的关于intern()的面试题,这道面试题还是有不小的难度,相信很多朋友看到 ...
- Java之String系列--intern方法的作用及原理
原文网址:Java之String系列--intern方法的作用及原理_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java的String的intern方法的原理. 常量池简介 在 JAVA 语言中 ...
- Java String的intern方法
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...
- intern string java_聊聊java String的intern
序 本文主要研究一下java String的intern String.intern() java.base/java/lang/String.java public final class Stri ...
- intern string java_Java-String.intern的深入研究
When---什么时候需要了解String的intern方法: 面试的时候(蜜汁尴尬)!虽然不想承认,不过面试的时候经常碰到这种高逼格的问题来考察我们是否真正理解了String的不可变性.String ...
- [转]String 之 new String()和 intern()方法深入分析
引入 String,是 Java 中除了基本数据类型以外,最为重要的一个类型了.很多人会认为他比较简单.但是和 String 有关的面试题有很多,下面我随便找两道面试题,看看你能不能都答对: Q1:S ...
最新文章
- 美媒人工智能(AI)代表了计算的优点,没有人类推理的缺点
- Java基础(二) 程序格式
- 算盘与电子计算机的区别之一是,算盘与电子计算机的区别之一是算盘没有存储能力...
- MySQL数据同步,出现Slave_SQL_Running:no和slave_io_running:no问题的解决方法
- 机器人学习--ROS/AMCL实现初始化粒子撒满整张地图和分步收敛
- c++primer plus 第11章 编程题第7题
- Zimbra开发接口文档API下载地址
- Python交互界面方向键、退格键乱码
- python 熊猫钓鱼_Python数据结构与算法之使用队列解决小猫钓鱼问题
- 风口猪炒股指标_低吸大长腿
- DS18B20温度传感器(STM32F103C8T6)
- 行人重识别论文阅读1-Watching You: Global-guided Reciprocal Learning for Video-based Person Re-identification
- 常用的抓包工具有哪些?
- click option/argument参数详解(click.option()和click.argument())
- Win7 电脑提高效率的快捷键+命令
- js操作图片像素进行编辑
- java移动小球_使用java实现持续移动的小球
- apk开发教程!安卓资深架构师分享学习经验及总结,技术详细介绍
- c# legend 显示位置_C# charting中图例(legend)的问题。
- ltspice语言中文_LTspice 一 简介(中文教程)
热门文章
- 服务器维护玩穿越火线,为什么我玩穿越火线进不去 三招助你轻松进入游戏
- 想要专升本你不得不看的全干货_吐血整理_专升本_计算机文化基础( 十 三 )
- setTimeout()方法
- Android刷新页面
- 便利店规模经营的条件是什么?
- 大数据存储引擎 NoSQL极简教程 An Introduction to Big Data: NoSQL
- Java基础案例2-4为新员工分配部门
- java实现录音功能
- 21点:赌场里最可能赢钱的游戏
- 「译」ECMAScript 提案:类型注解(TypeScript 在未来可能被纳入 ECMAScript 中)