定义:Class常量池可以理解为是Class文件中的资源仓库。
内容:Class文件中除了包含类的版本、字段、方法、接口等描述信息外, 还有一项信息就是常量池,用于存放编译期生成的各种字面量和符号引用。
我们可以通过一个命令来查看我们字节码文件的内容:
定义:字面量就是指由字母、数字等构成的字符串或者数值常量。
PS:字面量只可以右值出现【等号右边的值】如:int a = 1 这里的a为左值,1为右值。在这个例子中1就是字面量。
private int compute() { int a = 1;//符号引用:a 字面量:1 int b = 2;//符号引用:b 字面量:2 String c = "有梦想的肥宅";//符号引用:c 字面量:有梦想的肥宅 return a + b; }
符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量:
符号引用只有到运行时被加载到内存后,这些符号才有对应的内存地址信息,这些常量池一旦被装入内存就变成运行时常量池,也就引出了下面动态链接的概念。
动态链接:对应的符号引用在程序加载或运行时会被转变为被加载到内存区域的代码的直接引用。
例:compute()这个符号引用在运行时就会被转变为compute()方法具体代码在内存中的地址,主要通过对象头里的类型指针去转换直接引用。
字符串的分配和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能。JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化:
String s = "有梦想的肥宅"; // s :指向常量池中的引用
PS:这种方式创建的字符串对象,只会在常量池中。
创建步骤:
JVM会先去常量池中通过 equals(key) 方法,判断是否有相同的对象:
String s1 = new String("有梦想的肥宅"); // s1指向内存中的对象引用
PS:这种方式会保证字符串常量池和堆中都有这个对象,没有就创建,最后返回堆内存中的对象引用。
创建步骤:
因为有"有梦想的肥宅"这个字面量,所以会先检查字符串常量池中是否存在此字符串:
String s1 = new String("有梦想的肥宅"); String s2 = s1.intern(); //【intern:是一个native方法】 System.out.println(s1 == s2); //false
PS:这种方式创建的字符串对象,可能在常量池中存在,也可能不存在【常量池保存一个内存地址的引用,指向堆中对应的字符串对象】。
创建步骤:
还是会去常量池找看有没有"有梦想的肥宅"这个字符串:
PS:jdk1.6版本需要将 s1 复制到字符串常量池里
java中基本类型的包装类的大部分都实现了常量池技术(严格来说对象在堆上应该叫对象池),这些类是 Byte、Short、Integer、Long、Character、Boolean,另外两种浮点数类型的包装类则没有实现。
PS:Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,因为一般这种比较小的数用到的概率相对较大。
public class Test { public static void main(String[] args) { //1、5种整形的包装类Byte,Short,Integer,Long,Character的对象,在值小于127时可以使用对象池 Integer i1 = 127; //PS:这种调用底层实际是执行的Integer.valueOf(127),里面用到了IntegerCache对象池 Integer i2 = 127; System.out.println(i1 == i2);//输出true //2、当值大于127时,不会从对象池中取对象 Integer i3 = 128; Integer i4 = 128; System.out.println(i3 == i4);//输出false //3、用new关键词新生成对象不会使用对象池 Integer i5 = new Integer(127); Integer i6 = new Integer(127); System.out.println(i5 == i6);//输出false //4、Boolean类也实现了对象池技术 Boolean bool1 = true; Boolean bool2 = true; System.out.println(bool1 == bool2);//输出true //5、浮点类型的包装类没有实现对象池技术 Double d1 = 1.0D; Double d2 = 1.0D; System.out.println(d1 == d2);//输出false } }