2024-03-14  阅读(2)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/1889092887

回答

String 的 intern() 是一个用于字符串添加到字符串常量池中,它的作用是:当调用 intern() 方法时,如果常量池中已经该字符串,则返回池中的字符串;如果常量池中不存在该字符串,则根据版本的不同处理方式不同:

  • 如果在 JDK 7 以前,由于字符串常量池在永久代,intern() 会将这个字符串的副本添加到常量池中,并返回常量池中的引用。
  • 从 JDK 7 开始,字符串常量池被移到了Java堆内存中,则 intern() 则是将 Java 堆中的引用复制到字符串常量池中,而不是复制字符串副本,这样,intern() 会返回指向堆上已存在对象的引用。

intern() 是基于字符串常量池(String Pool)。字符串常量池是 Java 堆中(JDK 7 以后)的一部分,其目的是存储字符串字面量和显式调用intern()方法的字符串实例,这样可以减少Java虚拟机中相同内容字符串对象的数量,以节省内存资源。

注:JDK 6 以前,字符串常量池是在永久代,从 JDK 7 开始,字符串常量池被移至堆内存中,同时,在 JDK 8 ,Java 去掉了永久代。下面演示代码全部基于 JDK 21。

扩展

intern() 核心原理

JDK 中对 intern() 描述如下:

/**
  Returns a canonical representation for the string object.
  A pool of strings, initially empty, is maintained privately by the class String.
  When the intern method is invoked, if the pool already contains a string equal to
  this String object as determined by the equals(Object) method, then the string from
  the pool is returned. Otherwise, this String object is added to the pool and a
  reference to this String object is returned.
  
  It follows that for any two strings s and t, s.intern() == t.intern() is true if and
  only if s.equals(t) is true.
  
  All literal strings and string-valued constant expressions are interned. String
  literals are defined in section 3.10.5 of the The Java Language Specification.
  
  Returns:
  a string that has the same contents as this string, but is guaranteed to be from a
  pool of unique strings.
*/
public native String intern();

intern() 是一个 Native 方法,底层调用 C++ 的 StringTable::intern 方法。这段注释告诉了如下几个信息:

  • 当调用 intern() 方法时,如果常量池中已经该字符串,则返回池中的字符串;否则将此字符串添加到常量池中,并返回字符串的引用。
  • 对于任意两个字符串st,若 s.intern() == t.intern()true,当且仅当s.equals(t)true

intern() 看着很简单,使用起来也非常方便,但是要深入理解还是蛮有难度的。

PS:以下例子都是基于 JDK 21(JDK 7 以后执行结果都一样)

请看下面例子: