Java – 告诉String是否被实习?

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

你可以找出一个String是否被实现的唯一方法是调用intern()并检查它是否返回自己:

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

这显然有一个缺点,即在没有实习之前实施String

部分偏离主题,有一种方法可以使用Guava的Interner接口 (使用Interners类公开的实现)使用显式池进行“自定义”实习。 这样做的好处是可以让Interner本身(并且使用池)在不再引用时被垃圾收集。

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

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

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

  1. s被固定在字符串池中。 new String(s)new String(s)具有相同的内容,因此调用它的intern()将返回s 。 表达式的结果是true
  2. s不是在字符串池中实现的,而是另一个相等的String对象 – 让我们称之为s2intern()将返回s2 ,因此表达式的结果为false
  3. s不在字符串池中实现,并且任何String都不等于它。 在这种情况下, new String(s)将被插入到字符串池中,这很可能会修改字符串池。 因为这与s不是同一个String对象,所以表达式的结果为false

因此,上面的表达式将正确地测试s是否在字符串池中被实现。 以下测试certificate了这一点:

 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 

我们无法查看实习字符串的存储库,也无法获取所有实习字符串的集合。

测试,如果给定的字符串已被实现已经产生了一个很好的困境(顺便说一下测量的常见问题):测量本身可能会影响实习字符串的存储库;)

要测试,如果存储库包含给定的String,我们需要将该String与(最坏情况下)该存储库中的所有字符串进行比较 – 具有风险,JVM 我们开始比较之前将此引用字符串实例化…这将返回true虽然字符串在测试之前没有被实习;)

但除此之外,我没有看到任何实际用途,知道虚拟机是否已经实现了字符串。 实习很便宜,如果需要就可以实习。 (如果有实际用途, String类将提供本机测试方法)

一般来说,您不需要检查 – 只是intern他们以确保或不依赖实习。 如果您需要实习或非实习字符串进行测试或试验,您可以制作它们:

实习:

 s = someArbitraryString.intern(); 

非实习:

 s = new String(someArbitraryString);