Java String intern()方法

时间:2020-01-09 10:34:54  来源:igfitidea点击:

这篇文章深入介绍了Java String intern()方法,该方法与Java中的"内部"字符串概念以及Java中的String池维护紧密相关。

Java中的字符串interning

在Java中,字符串文字是" interned"的,以便共享唯一的实例。最初为空的字符串池由String类私有维护。对于每个字符串文字(用双引号引起来的字符串值),JVM都会在字符串池中扫描具有相同值的任何字符串(如果返回的是相同的引用)。因此,不会为相同的字符串分配新的内存,而是使用现有的内存并共享引用。

让我们看一个例子。如果按以下方式创建两个字符串,则:

String str1 = “Hello”
String str2 = “Hello”

然后两个对象都引用相同的内存。

字符串中的intern方法

字符串文字在Java中默认为Internated,但对于使用new运算符创建的字符串则不是这样。对于此类String实例,内存是在堆上分配的,而不是在String池中分配的。

例如,如果创建四个字符串,如下所示:

String str1 = “Hello”;
String str2 = “Hello”;
String str3 = new String(“Hello”);
String str4 = new String(“Hello”);

str1和str2在常量字符串池中共享相同的引用,其中str3和str4对堆上的内存位置具有单独的引用。

即使对于使用new运算符创建的String,也可以使用Java String中的intern()方法从池中获取String对象(如果已经存在相同的值)。

  • public String intern()–返回字符串对象的规范表示。调用intern方法时,如果池已经包含等于equals(Object)方法确定的此String对象的字符串,则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

Java intern()方法示例

让我们尝试借助几个示例来了解字符串实习。

public class StringInterning {
  public static void main(String[] args) {
    // Stored in String pool
    String str1 = "Hello";
    // Stored in String pool
    String str2 = "Hello";
    // Stored in heap
    String str3 = new String("Hello");
    // returns true
    if(str1 == str2) {
      System.out.println("str1 and str2 are pointing to same memory reference");
    }else{
      System.out.println("str1 and str2 are not pointing to same memory reference");
    }		
    // returns false
    if(str1 == str3) {
      System.out.println("str1 and str3 are pointing to same memory reference");
    }else{
      System.out.println("str1 and str3 are not pointing to same memory reference");
    }
    // shares the reference in String pool
    String str4 = str3.intern();
    // returns true
    if(str1 == str4) {
      System.out.println("str1 and str4 are pointing to same memory reference");
    }else{
      System.out.println("str1 and str4 are not pointing to same memory reference");
    }
  }
}

输出:

str1 and str2 are pointing to same memory reference
str1 and str3 are not pointing to same memory reference
str1 and str4 are pointing to same memory reference

在示例中,字符串str1和str2创建为字符串文字,并且具有相同的值,因此这两个对象在字符串池中共享相同的引用。这就是为什么使用相等运算符('==')比较它们会返回true的原因。

字符串str3是使用new运算符创建的,因此它的内存在堆中分配。即使str3与str1和str2具有相同的值,但它不会共享相同的引用。这就是为什么使用相等运算符('==')将String str3与str1或者str2比较时返回false的原因。

字符串str4是使用intern方法创建的,因此如果这样的值已经存在,它将查找字符串池。由于值" Hello"已经在池中,因此str4与str1和str2共享引用。这就是为什么使用相等运算符('==')比较str4与str1或者str2会返回true的原因。

这是另一个使用intern()方法的Java程序。

public class StringInterning {
  public static void main(String[] args) {
    // Stored in heap
    String str1 = new String("Hello");
    // Stored in heap
    String str2 = new String("Hello");
    // returns false
    if(str1 == str2) {
      System.out.println("str1 and str2 are pointing to same memory reference");
    }else{
      System.out.println("str1 and str2 are not pointing to same memory reference");
    }
    String str3 = str1.intern();
    // returns false
    if(str1 == str3) {
      System.out.println("str1 and str3 are pointing to same memory reference");
    }else{
      System.out.println("str1 and str3 are not pointing to same memory reference");
    }
    // store in the pool
    String str4 = "Hello";
    // returns true
    if(str3 == str4) {
      System.out.println("str3 and str4 are pointing to same memory reference");
    }else{
      System.out.println("str3 and str4 are not pointing to same memory reference");
    }
  }
}

输出:

str1 and str2 are not pointing to same memory reference
str1 and str3 are not pointing to same memory reference
str3 and str4 are pointing to same memory reference

在示例中,字符串str1和str2使用new运算符创建,因此创建了两个单独的对象。这就是为什么使用相等运算符('==')比较它们会返回false的原因。

字符串str3是使用intern()方法创建的,因此str3的内存在池中分配。这就是为什么使用相等运算符('==')将str3与str1或者str2比较时返回false的原因。

字符串str4创建为字符串文字,因此将检查字符串池以查看是否已存在该值。已经存在相同的值,因此str4与str3具有相同的引用。这就是为什么使用相等运算符('==')比较str3和str4返回true的原因。