Java中字符串的实习
String Interning 是一种仅存储每个不同 String 值的副本的方法,该副本必须是不可变的。
通过在几个字符串上应用 String.intern() 将确保具有相同内容的所有字符串共享相同的内存。例如,如果名称“Amy”出现 100 次,通过实习可以确保只有一个“Amy”实际分配了内存。
这对于减少程序的内存需求非常有用。但请注意,缓存由 JVM 在永久内存池中维护,与堆相比,其大小通常有限,因此如果您没有太多重复值,则不应使用实习生
intern() 方法:在Java中,当我们使用 intern() 方法执行任何操作时,它会返回字符串对象的规范表示。池由 String 类管理。
- 当 intern() 方法被执行时,它会检查与此 String 对象相等的字符串是否在池中。
- 如果可用,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对该 String 对象的引用。
- 由此可见,对于任何两个字符串s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。
建议使用 equals(),而不是 ==,来比较两个字符串。这是因为 ==运算符比较内存位置,而 equals() 方法比较存储在两个对象中的内容。
// Java program to illustrate
// intern() method
class GFG {
public static void main(String[] args)
{
// S1 refers to Object in the Heap Area
String s1 = new String("GFG"); // Line-1
// S2 refers to Object in SCP Area
String s2 = s1.intern(); // Line-2
// Comparing memory locations
// s1 is in Heap
// s2 is in SCP
System.out.println(s1 == s2);
// Comparing only values
System.out.println(s1.equals(s2));
// S3 refers to Object in the SCP Area
String s3 = "GFG"; // Line-3
System.out.println(s2 == s3);
}
}
输出:
false
true
true
说明:每当我们创建一个字符串对象时,都会创建两个对象,即堆区中的一个和字符串常量池中的一个,并且字符串对象引用始终指向堆区对象。当 line-1 执行时,它将创建两个对象并指向堆区域创建的对象。现在当第 2 行执行时,它将引用 SCP 中的对象。同样,当第 3 行执行时,它指的是在 SCP 区域中的同一个对象,因为内容已经在 SCP 区域中可用。无需创建新的 one 对象。
如果相应的字符串常量池(SCP)对象不可用,则 intern() 方法本身将创建相应的 SCP 对象。
// Java program to illustrate
// intern() method
class GFG {
public static void main(String[] args)
{
// S1 refers to Object in the Heap Area
String s1 = new String("GFG"); // Line-1
// S2 now refers to Object in SCP Area
String s2 = s1.concat("GFG"); // Line-2
// S3 refers to Object in SCP Area
String s3 = s2.intern(); // Line-3
System.out.println(s2 == s3);
// S4 refers to Object in the SCP Area
String s4 = "GFGGFG"; // Line-4
System.out.println(s3 == s4);
}
}
输出:
true
true
解释:我们使用 intern() 方法来获取相应 SCP 对象的引用。在这种情况下,当 Line-2 执行时,s2 将具有值“GFGGFG”,它只会创建一个对象。在第 3 行中,我们尝试在 SCP 区域实习 s3,这又与 s2 一起。 s4 也在 SCP 中,因此在比较时,所有输出都为真。