String
Java中的字符串对象(String)既可以存在于堆中,也可以存在于常量池中,这取决于如何创建和初始化它们。
当使用字面值方式创建字符串对象时(例如:String str = “Hello”),Java会首先检查常量池中是否已经存在该字符串,如果存在则直接返回其引用,否则会在常量池中创建一个新的对象,并返回其引用。因此,此时的字符串对象实际上是在常量池中创建的。
当使用new关键字显式地创建字符串对象时(例如:String str = new String(“Hello”)),Java会在堆中创建一个新的对象,并将其初始化为包含指定字符串的副本。因此,此时的字符串对象实际上是在堆中创建的。
需要注意的是,通过调用intern()方法可以将堆中的字符串对象加入到常量池中,从而可以利用常量池中的字符串对象的优势,例如避免重复创建相同的字符串。
Integer:
Java中的Integer对象可以存储在堆中或者常量池中,具体取决于如何创建该对象。
通过valueOf()方法创建的Integer对象会首先从常量池中查找是否已经存在该值的Integer对象,如果存在则直接返回常量池中的对象,否则会创建一个新的Integer对象并存储在常量池中。例如:
Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
System.out.println(a == b); // 输出:true,因为a和b都指向了常量池中同一个Integer对象
对于超出[-128, 127]范围的Integer对象,无论是通过valueOf()方法还是new关键字创建的,都会在堆中创建新的对象。例如:
Integer c = Integer.valueOf(128);
Integer d = new Integer(128);
System.out.println(c == d); // 输出:false,因为c和d分别指向了不同的堆中的Integer对象
因此,Java中的Integer对象可能存储在堆中或常量池中,具体取决于它们是如何创建的。
以下
包装类型:
包装类型的对象才会被放入常量池中:
- Boolean
- Byte
- Character (只有当字符在
\u0000
和\u007f
之间时才会被缓存) - Short 和 Integer (-128到127之间的整数会被缓存)
- Long (-128到127之间的长整数会被缓存)
- 这些包装类型的对象被缓存在常量池中是为了提高性能和节省内存。这意味着如果创建具有相同值的两个整数对象,它们将引用相同的对象,而不是创建两个对象。
- 需要注意的是,使用构造函数显式创建这些对象时,它们不会被缓存到常量池中。例如,使用
new Integer(10)
创建一个Integer对象时,它不会被缓存。但是,使用 Integer.valueOf(10) 方法创建的Integer对象将会被缓存。 - 最后,需要注意的是,在Java 9及更高版本中,这些缓存行为已经发生了变化,并且可以通过JVM参数来控制这些行为。