java常量池详解

java常量池分为Class常量池、运行时常量池和字符串常量池

Class常量池

class文件中除了类的版本、字段、方法、接口等信息等,还有class常量池,它用于存放编译阶段生成的各种字面量和符号引用。
字面量: 给基本类型变量赋值的字面量或者说是字面值,
如int i = 6;String str = “abc”,这里的6和“abc”都是字面量;
符号引用: Java程序在编译成class文件时,虚拟机并不知道类(接口)、类中引用对象、字段名称和描述符、方法名称和描述符的实际地址,就用符号引用来代替,在类装载器装载类时会通过符号引用得到真实地址(实际内存地址)。

字符串常量池

注:这个概念是有争议的
jdk1.8中字符串常量池是放在堆中的,需要了解透彻字符串String
String对象是对char[]数组封装实现的对象:
在这里插入图片描述
其中String类被final修饰,其中char数组也被private final修饰,这也导致了他的不可变性,这种不可变性给Java带来了以下几点好处:

  1. 保证了String的安全性;
  2. 保证 hash 属性值不会频繁变更,确保了唯一性,使得类似 HashMap 容器才能实现相应的 key-value 缓存功能;
  3. 可以实现字符串常量池。在 Java 中,通常有两种创建字符串对象的方式,一种是通过字符串常量的方式创建,如 String str=“abc”;另一种是 字符串变量通过 new 形式的创建,如 String str = new String(“abc”)。

String的创建方式及内存分配的方式

  1. String str1 = “abc”;
    当代码中是这种创建方式时,jvm会先去字符串常量池检查是否有“abc",如果有,就返回该对象引用,否则就在字符串常量池中区创建;
  2. String str2 = new String(“abc”);
    在编译期,字符常量"abc"会被放在常量结构中,在类加载时,“abc"会在常量池中创建,在调用new时,jvm命令会调用String构造函数,同时在堆中创建一个String对象引用常量池中的"abc”,最后栈中的str2引用这个String对象。
    其中将常量池中的"abc"引用到堆中具体是先将常量池中的对象压入栈中,在使用String方法的构造器时,去拿到栈中的字符串作为构造方法的参数,这个构造函数是一个char[]数组的赋值过程,而不是new 出来的,所以是引用了常量池中的对象。
  3. String str3 = “ab”+“cd”+“ef”;
    编译器会自动优化为String str3 = “abcdef”,而不会一个个去创建对象;
    String str4 = “gh”;String str5 = “abc”+str4;这里不会优化;
  4. 循环中使用+
    在这里插入图片描述
    其中在进行字符串拼接时,编译器会自动优化,偏向使用StringBuilder
    intern
    String的intern方法,如果常量池中有这个字符串就会返回这个字符串的引用。
    如果需要查看 String 的编译优化,需要使用到反编译工具,推荐 JD-GUI:http://java-decompiler.github.io/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值