java常量池总结

1.class常量池

在JAVA中,Java类(.java)文件被编译后就会形成一份class文件;class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是class常量池,用于存放编译器生成的各种字面量符号引用,每一个class文件都有一个对应的class常量池。
其中各种字面量包括:
1.文本字符串
2.八种基本类型的值
3.被声明为final的常量
符号引用包括:
1.类和方法的 全限定名
2.字段的名称和描述符
3.方法的名称和描述符

2.运行时常量池

运行时常量池存在与内存中,也就是class常量池被加载到内存之后的版本,是方法区的一部分(JDK1.8中运行时常量池在元空间,元空间也是方法区的一种实现)。不同之处:它的字面量可以动态的添加(String类的intern()),符号引用可以被解析为直接引用。
JVM在执行某个类的时候,必须经过加载、连接、初始化,而在连接的过程中又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,这里所说的常量包括:基本类型包装类(包装类不管理浮点型,整形只会整理-128到127)和字符串类型(即通过String.intern()方法可以强制将String放入常量池),运行时 常量池是每个类私有的。在解析阶段,会把符号引用替换为直接引用。

3.基本类型包装类常量池

Java基本类型的包装类的大部分都实现了常量池技术。Byte,Short,Integer,Long这4种包装类默认创建了数值[-128,127]的相应类型来缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean直接返回True或False,如果超出对应范围就会去创建新的对象。两种浮点数类型的包装类Float,Double并没有实现常量池技术。
Integer源码缓存实现
在这里插入图片描述
在这里插入图片描述
注意
所有整型包装类对象值的比较,全部使用equals方法比较。
对于Integer var = ?在-128在127之间的赋值,var这个对象会在上文图片中的IntegerCache中的cache[]数组中,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间外的所有数据,都会在堆上产生,并不会复用已有对象,推荐使用equals方法进行判断。

4.字符串常量池

在JDK1.6及之前的版本,字符串常量池存放在方法区中间,在JDK1.7版本以后,字符串常量池就被移到堆中了。HotSpot VM中,记录interned string的一个全局表叫StringTable,它本质上就是个HashSet;这个StringTable在每个HotSpot VM的实例只有一份,被所有类共享。
注意:它只存储对java.lang.String实例的引用,而不存储String对象的内容
字符串常量池和上面的基本类型包装类常量池有些不用,字符串常量池没有事先的缓存一下数据,而是如果要创建的字符串在常量池内存中就返回对象的引用,如果不存在就创建一个放在常量池中。
在Java中,有两种创建字符串对象的方法,一种是字面量直接创建,另一种是new一个String对象,这两种方法创建字符串对象的过程是不一样的。

String str1 = "abc";   //(1)
String str2 = new String("abc")   //(2)

如果是第一种方式创建对象,因为在编译时确定的,如果该字符串不在常量池中则会将该字符串放入常量池中并返回字符串对象的引用,如果在常量池中则直接返回字符串对象的引用;如果是第二种方式创建对象,因为要创建String类型的对象,而String对象是在运行时才加载到内存的堆中的,属于运行时创建,所以要先在堆中创建一个String对象,再去常量池中寻找是否有相同的字符串,如果有就返回堆中的String对象引用,如果没有则在将该字符串加入常量池中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值