Java:为什么只为String值维护常量池?

我的问题是关于java实习和常数池。

Java为java.lang.String维护一个常量池,巧妙地使用JVM内存,并且这样做java.lang.String是不可变的。 那么为什么java不维护其他不可变类型的常量池,例如Long,Integer,Char,Short? 那不会节省内存吗?

我知道整数被汇集到值范围[-127,127],但我不明白选择这个范围的原因。

这是我编写的测试代码,用于测试其他不可变数据类型的池。

 public class PoolTest { public static void main(String... args) { // Pooling of Integer [-127, 127] Integer x = 127, y = 127; System.out.println("Integer:" + (x == y)); // prints true x = 129; y = 129; System.out.println("Integer:" + (x == y)); // prints false // Apparent pooling of short [-127, 127] Short i = 127, j = 127; System.out.println("Short: " + (i == j)); // prints true i = 128; j = 128; System.out.println("Short: " + (i == j)); // prints false // No pooling of long values Long k = 10L, l = 10L; System.out.println("Long: " + (i == j)); // prints false k = 128L; l = 128L; System.out.println("Long: " + (i == j)); // prints false } } 

常量池的目的是通过保留多个常量副本来减少所需的内存开销。 在String的情况下,JVM本身就需要为每个可单独区分的常量保留一些对象,而Java规范基本上说JVM应该在类加载时重复删除String对象。 通过intern手动将String放入池中的能力很低,并且允许程序员识别将在程序生命周期中出现的特定值(例如属性)并告诉JVM将它们放在正常的垃圾收集。

另一方面,汇集数字常量并没有多大意义,原因如下:

  • 大多数特定数字都不会在给定程序的代码中使用。
  • 当在代码中使用数字时,将它们作为立即操作码值嵌入代码中在内存方面比试图汇集它们更便宜。 请注意,即使是空String也会携带char[] ,其长度为int ,而hashCode则为另一个。 相反,对于数字,最多需要八个立即字节。
  • 从最近的Java版本开始,出于性能原因,预先设置了从-128到127( Character为0到127)的ByteShortInteger对象,而不是为了节省内存。 大概选择此范围是因为这是有符号字节的范围,并且它将涵盖大量常见用途,而尝试预先处理大量值是不切实际的。

需要注意的是,请记住,在Java 5中引入自动装箱和generics类型之前很久就已经制定了关于实习的规则,这大大扩展了随机使用的包装类的数量。 使用量的增加导致Sun将这些常见值添加到常量池中。

好吧,因为String对象是不可变的,所以多个引用“共享”相同的String对象是安全的。

 public class ImmutableStrings { public static void main(String[] args) { String one = "str1"; String two = "str1"; System.out.println(one.equals(two)); System.out.println(one == two); } } // Output true true 

在这种情况下,实际上不需要生成相同String对象的两个实例。 如果可以更改String对象,可以更改StringBuffer,我们将被迫创建两个单独的对象。 但是,正如我们所知,String对象无法更改,我们可以安全地在两个String引用中共享一个String对象,一个和两个。 这是通过String文字池完成的。

您可以通过此链接详细了解。