Java进阶——Java中的字符串常量池
字符串常量池
JVM为了减少字符串对象的重复创建,其内部维护了一个特殊的内存,这段内存被成为字符串常量池(方法区中)。实际上还有整型常量池、浮点型常量池等等。字符串常量池存放的是对象的引用,而不是对象。Java中字符串对象创建有两种形式:字面量形式和创建对象形式
1、字面量形式
字面量的体现形式String str = "Hello"
,简单理解为去字符串常量池中拿对象的引用
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用
2、创建对象形式
创建对象的体现形式String str = new String("Hello");
,简单理解为直接在堆内存空间中创建新的对象
当代码中出现了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象的引用,首先它都会去创建这个字符串对象,这里字符串对象指的是String对象,String对象存放在堆当中。然后它会去字符串常量池寻找Hello这个字符串,其处理的结果同字面量形式。最终str引用指向String对象的引用
字符串对象创建
1、String str = new String(“abc”) 创建多少个对象?2个
- 在常量池中查找是否有”abc”对象,有则返回对应的引用实例,没有则创建对应的实例对象(1个)
- 在堆中 new 一个 String(“abc”) 对象(1个)
- 将对象地址赋值给str,创建一个引用
2、String str = new String(“A”+”B”)创建多少个对象?4个
- 在常量池中查找,字符串”A”,”B”,”AB”(3个)
- 在堆中 new 一个 String(“AB”) 对象(1个)
- 将对象地址赋值给str,创建一个引用
问题抛出
问:求解下面的输出语句的结果并解释原因
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
// == :比较两个对象是否为同一对象
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s9); // false
System.out.println(s4 == s5); // false
System.out.println(s1 == s6); // true
问题分析
1、s1==s2
s1和s2在赋值时,均使用的字符串字面量。在编译期间,这种字面量会直接放入常量池中,从而实现复用。在载入运行时常量池后,s1和s2指向的是同一个内存地址
2、s1==s3
s3是动态拼接出来的字符串,但是所有参与拼接的部分都是已知的字面量。在编译期间,这种拼接会被优化,编译器直接帮你拼好,因此s3会被优化成String s3 = "Hello"
3、s1==s4
s4是动态拼接出来的字符串,但new String("lo")
这部分不是已知字面量,是一个不可预料的部分。在编译期间,编译器不会优化,必须等到运行时才可以确定结果
4、s1==s9
s7和s8在赋值的时候使用的字符串字面量,但是拼接成s9的时候,s7和s8作为两个变量,都是不可预料的。编译器毕竟是编译器,不可能当解释器用,所以不做优化。等到运行时,s7和s8拼接成的新字符串,在堆中地址不确定,不可能与方法区常量池中的s1地址相同
5、s4==s5
s4和s5都创建出了字符串对象,两者都存在于堆中,但地址不相同
6、s1==s6
对于使用new创建的字符串对象,如果想将这个对象的引用加入到字符串常量池,可以使用intern方法。调用intern后,首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。很显然,s1和s6都已经是字符串常量池中的一员,且值是相等的,所以引用的地址也相等
Java进阶——Java中的字符串常量池的更多相关文章
- Java中String字符串常量池总结
最近到广州某建站互联网公司面试,当时面试官问假设有两个字符串String a="abc",String b = "abc";问输出a==b是true还是fals ...
- Java中String字符串常量池
首先看一个例子,通过这个例子更能快速理解String常量池 public static void main(String[] args) { String a = "ab"; St ...
- 转载:Java中的字符串常量池详细介绍
引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重 ...
- Java中的字符串常量池,栈和堆的概念
问题:String str = new String(“abc”),“abc”在内存中是怎么分配的? 答案是:堆内存.(Tips:jdk1.8 已经将字符串常量池放在堆内存区) 题目考查的为Ja ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- Java中的字符串常量池和JVM运行时数据区的相关概念
什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...
- Java中的字符串常量池?
参考:http://droidyue.com/blog/2014/12/21/string-literal-pool-in-java/index.html
- Java字符串常量池是什么?为什么要有这种常量池?
简单介绍 Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池.我们知道String是java中比较特殊的类,我们可以使用new运算符创建String对象,也可以用双引 ...
- Java String类相关知识梳理(含字符串常量池(String Pool)知识)
目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...
随机推荐
- BZOJ 3561: DZY Loves Math VI 莫比乌斯反演+复杂度分析
推到了一个推不下去的形式,然后就不会了 ~ 看题解后傻了:我推的是对的,推不下去是因为不需要再推了. 复杂度看似很大,但其实是均摊 $O(n)$ 的,看来分析复杂度也是一个能力啊 ~ code: #i ...
- Install Python3.6 on Amazon Linux/EC2 在Amazon Linux实例中安装使用Python3.6
本文转载自 https://gist.github.com/niranjv/f80fc1f488afc49845e2ff3d5df7f83b 由于Amazon Linux中预装的Python版本为2. ...
- mac 安装注册Charles
软件去官网下载安装即可. 下载地址:https://www.charlesproxy.com/download/ 适用于Charles任意版本的注册码Charles 4.2.7 目前是最新版,可用. ...
- Linux查看文件的权限
Linux查看权限命令: ls -l 文件或文件夹 输出结果示例: 这里是查看tomcat文件夹中所有子文件或者子文件夹的权限,以列表的形式列出. 关于列表的每列所代表的含义参见我的另外一篇博客:Li ...
- 一个半吊子PM的反思
故事之源 2019年3月,也就是2016级计算机学院的大三时,软件工程这门课程由选修转为专业必修课,而七个葫芦娃共聚罗杰老师的课堂,组成葫芦娃不想写代码小分队.面临着继承往届项目.完成指定项目和自选项 ...
- 第08组 Beta冲刺(3/4)
队名 八组评分了吗 组长博客链接(2分) 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 了解各个小组的进度与难以攻破的地方,晚上安排开会,安排新的冲刺任务. 重新分配小组及个人任务. ...
- mvn命令修改pom打包的版本号
在java项目中打包经常需要修改镜像的版本号.可以使用如下命令 mvn versions: // 如果要打包使用人如下命令,打印详细信息使用 -X mvn clean deploy -e -Dskip ...
- 如何防止Hangfire重复作业在连续执行30分钟后重新启动(How to prevent a Hangfire recurring job from restarting after 30 minutes of continuous execution)
var options = new SqlServerStorageOptions { InvisibilityTimeout = TimeSpan .FromMinutes(30)//默认值}; G ...
- mysql5.7的主从切换
mysql5.7的主从切换 主库: master 10.11.0.211 从库: slave 10.11.0.210 目标:主从切换,将slave切换为master,master切换为slave 一. ...
- 《Effective Java》第2章 对所有对象都通用的方法
第10条:覆盖equals时,请遵守通用约定 1.使用==来比较两个对象的时候,比较的是两个对象在内存中的地址是否相同(两个引用指向的是否为同一个对象):Object中定义的equals方法也是这样比 ...