前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM-深入学习字符串常量池

JVM-深入学习字符串常量池

作者头像
晓果冻
发布2022-09-08 13:53:53
3120
发布2022-09-08 13:53:53
举报
文章被收录于专栏:一直在努力的Java菜鸡er

JVM-深入学习字符串常量池

第一二张图应该画错了,元空间的时候,字符串常量池已经移入堆内

首先声明,在JDK1.7的时候,字符串常量池已经从方法区迁移到了堆内存,JDK1.8的时候方法区改朝换代为元空间,同时也不在占用JVM内存,而是使用本地内存

为什么多设计一个常量池,不能像其它对象一样乖乖待在堆中吗?鄙人大胆猜测:

  • 对象的分配需要时间和空间的开销,一般在程序中。字符串使用的频段还是很高的,另一方面,常用的数据库密码、用户名啥的都是使用字符串保存的,如果不将其放入字符串常量池的话,使其频繁创建销毁的话,性能和安全性都是划不来的,所以这就是为什么会有字符串常量池和String为什么是final修饰的原因。

上代码,下面这种字面量声明的方式是我们最常用的方式。这样声明会直接将字符串”晓果冻“放入字符串常量池

再声明一个对象s2,因为“晓果冻”已经在字符串常量池中存在了,所以s2直接指向字符串常量池中的地址

代码语言:javascript
复制
String s2 = "晓果冻";

new String("")呢,分2种情况

  1. new的字符串已经在常量池存在,那么堆就会指向字符串常量池中的地址

​ 为什么会是false呢,因为s1引用的是字符串常量池中的地址,s2引用的是堆内地址,但堆内对象是引用了字符串地址的,如果 s2 = s2.intern();

其实这里也不能算第二种情况,就是new好了再调用上面的**intern()**方法,又是另一种情形;

intern():不管使用什么方式定义一个字符串,都会首先在常量池中查找是否有相应的字符串存在,如果有,直接返回引用,否则,在常量池中生成相应的字符串并返回引用;

下面上代码

代码语言:javascript
复制
package com.company;

public class Main {

    public static void main(String[] args) {
	// write your code here
        String s1 = "晓果冻";
        String s2 = "晓果冻";
        String s3 = "晓" + "果冻";
        String s4 = new String("晓");
        String s5 = new String("果冻");
        String s6 = s4 + "果冻";
        String s7 = s4 + s5;
        String s8 = s6.intern();
        String s9 = s7.intern();
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1 == s6);
        System.out.println(s6 == s7);
        System.out.println(s6 == s8);
        System.out.println(s8 == s9);
        System.out.printf(s7);
    }
}

+号操作是有内部优化处理操作的,其实也是又new了一个新的字符串对象,所以上图字符串常量池中的"晓"和"果冻"字符串没有被引用。因为这种+操作这种图我不知道该怎么画,所以只能指向最终的堆中地址。

代码语言:javascript
复制
s6.intern()如果不把返回值赋值给s6,那么栈内存中的对象s6还是引用堆中的地址。
只有s6=s6.intern();//这样栈内存中的对象s6才会引用常量池中的地址,故s1==s6
代码语言:javascript
复制
String s10 = new String("晓果冻");

/如果字符串常量池中没有"晓果冻"字符串的话,那么直接在堆中创建该字符串,并不会复制一份到字符串常量池的,大多数人都会以为会复制一份到字符串常量池,其实不然。 只有当s10.intern();在常量池新增了一个对象,但是并没有将字符串复制一份到常量池,而是直接指向了之前已经存在于堆中的字符串对象。因为在 JDK 1.7 之后,字符串常量池不一定就是存字符串对象的,还有可能存储的是一个指向堆中地址的引用

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JVM-深入学习字符串常量池
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档