Java常量池
Java 常量池是 Java 运行时环境中的一个特殊存储区域,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入到方法区的运行时常量池中。
Java 常量池主要可以分为以下几类:
-
字符串常量池:这是 Java 常量池中最为人所知的一种。主要用于存储字符串字面量,当使用
String
类的intern()
方法时,如果常量池中已经包含一个等于此String
对象的字符串,则返回代表池中这个字符串的String
对象的引用;否则,将此String
对象包含的字符串添加到常量池中,并返回此String
对象的引用。 -
整型常量池:Java 5 引入的自动装箱机制,使得基本数据类型和它们对应的包装类之间可以自动转换。在 Java 5 以后,为
Integer
和Byte
、Short
、Long
、Character
这些包装类提供了缓存机制,当数值在一定范围内(-128 到 127 之间)时,可以直接从缓存中获取对象,而不是每次都创建一个新的对象。 -
Class 常量池:每个类被加载后,它的信息会被放入到运行时常量池中,包括类的版本、字段、方法、接口等描述信息。这是 JVM 实现动态链接的重要部分。
-
其他:除了上述几种常量池,Java 运行时常量池中还可能包含其他类型的常量,比如浮点型常量等。
常量池的设计主要是为了提供一种机制,使得相同的常量在内存中只有一份拷贝,从而节省内存空间,提高程序的运行效率。
示例演示
在Java中,常量池是一个非常重要的概念,它用于存储编译期生成的各种字面量和符号引用。
下面将通过几个示例来详细讲解Java常量池的工作原理和特点。
示例一:字符串常量池
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1 == str2); // 输出 true
System.out.println(str1 == str3); // 输出 false
解释:
str1
和str2
都是通过字符串字面量创建的,它们在编译期就被确定,并且被存储在字符串常量池中。由于str1
和str2
指向常量池中同一个字符串对象,因此str1 == str2
的结果为true
。str3
是通过new String("Hello")
创建的,这种方式会在堆上创建一个新的字符串对象,即使内容与常量池中的字符串相同,它们也是两个不同的对象,因此str1 == str3
的结果为false
。
示例二:使用intern()方法
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = str2.intern();
System.out.println(str1 == str2); // 输出 false
System.out.println(str1 == str3); // 输出 true
解释:
str1
是通过字符串字面量创建的,存储在字符串常量池中。str2
是通过new String("Hello")
在堆上创建的,与常量池中的字符串内容相同,但它们是两个不同的对象。str2.intern()
方法会检查字符串常量池中是否已经存在与str2
内容相同的字符串,如果存在,则返回常量池中该字符串的引用;如果不存在,则将str2
的引用添加到常量池中,并返回该引用。由于常量池中已经存在"Hello"
,因此str3
指向常量池中的字符串,与str1
相同。
示例三:整型常量池
Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1 == i2); // 输出 true
System.out.println(i3 == i4); // 输出 false(在大多数情况下)
解释:
- 对于基本数据类型的包装类,如
Integer
,Java 提供了缓存机制来优化性能。在 JDK 1.5 及以上版本中,对于-128
到127
之间的整数,Integer
类会缓存这些值,当使用Integer.valueOf(int i)
方法时,如果i
在这个范围内,就会直接返回缓存中的对象。 - 因此,
i1
和i2
都是指向缓存中的同一个Integer
对象,所以i1 == i2
的结果为true
。 - 对于超出范围的整数(如
128
),每次调用Integer.valueOf()
都会创建一个新的对象,因此i3
和i4
指向不同的对象,i3 == i4
的结果为false
。
需要注意的是,虽然示例三展示了整型常量池的概念,但实际上这个范围(-128
到 127
)是可以通过系统属性 java.lang.Integer.IntegerCache.high
来调整的。
通过以上示例,我们可以看到 Java 常量池在优化内存使用和提高程序性能方面的重要作用。
常量池中的字符串和整型常量等,通过共享机制减少了内存中的重复对象,从而提高了程序的运行效率。
欢迎访问我的(夏壹分享)公众号 和 博客(sanzhiwa)后缀top