Java - 判断字符串是否被拘禁?

2022-09-03 14:11:28

所以这里的问题很简单:有没有办法判断Java中的一个是否被拘留?我的猜测是否定的,但我想知道是否有人知道得更好。String


答案 1

您可以确定是否被拘留的唯一方法是打电话并检查它是否返回自己:Stringintern()

boolean hasBeenInternedBefore = myString.intern() == myString;

这显然有一个缺点,即在以前没有被拘留的时候进行实习。String

部分偏离主题,有一种方法可以使用GuavaInterner接口(使用Interners公开的实现)通过显式池进行“自定义”实习。这样做的好处是,当不再引用它时,能够让它本身(以及池)被垃圾回收。Interner


答案 2

有一种方法可以检查特定对象是否已暂存,但如果这些内容尚未暂存,则会将内容插入到字符串池中。创建一个具有相同内容的新对象,将其插入,并与原始对象进行比较:StringString

new String(s).intern() == s

这是有效的,因为.考虑每种可能的情况:new String(s) != s

  1. s在字符串池中实习。 具有相同的内容,因此调用它将返回。表达式的结果是 。new String(s)sintern()strue
  2. s不在字符串池中,但另一个相等的对象是 — 我们称之为 。 将返回 ,因此表达式的结果是 。Strings2intern()s2false
  3. s不被禁在字符串池中,并且两者都不等于它。在这种情况下,将被暂储到字符串池中,不幸的是,这会修改字符串池。因为 这与 对象不同,所以表达式的结果是 。Stringnew String(s)Stringsfalse

因此,上述表达式将正确测试是否在字符串池中滞留。以下测试演示了这一点:s

public static void main(String[] args) {
    String interned = new String(new char[] { 'i', 'n', 't' }).intern();
    String notInterned = new String(new char[] { 'n', 'o', 't' });
    System.out.println("Case 1: " + wasInterned(interned));
    System.out.println("Case 2: " + wasInterned(new String(interned)));
    System.out.println("Case 3: " + wasInterned(notInterned));
}

public static boolean wasInterned(String s) {
    return new String(s).intern() == s;
}

运行时,输出为:

 Case 1: true
 Case 2: false
 Case 3: false