所以这里的问题很简单:有没有办法判断Java中的String
是否被实现?我的猜测是否定的,但我想知道是否有人知道更好。
你可以找出String
是否被实施的唯一方法是调用intern()
并检查它是否自行返回:
boolean hasBeenInternedBefore = myString.intern() == myString;
这显然有缺点,当String
之前没有被实习时实习。
部分偏离主题,有一种方法可以使用Interner
interface的Guava(使用Interners
class公开的实现)使用显式池进行“自定义”实习。这样做的好处是能够让Interner
本身(以及游戏池)在不再被引用时被垃圾收集。
有一种方法可以检查特定的String
对象是否已经被实现,但如果这些内容尚未实现,它会将内容插入到字符串池中。使用相同的内容创建一个新的String
对象,实习,并与原始对象进行比较:
new String(s).intern() == s
这是因为new String(s) != s
的事实。考虑每种可能的情况:
s
被固定在字符串池中。 new String(s)
与s
具有相同的内容,所以intern()
呼吁它将返回s
。表达式的结果是true
。s
不是在字符串池中实习,而是另一个相同的String
对象 - 让我们称之为s2
。 intern()
将返回s2
,因此表达式的结果是false
。s
没有被插入字符串池中,也没有任何String
等于它。在这种情况下,new String(s)
将被插入到字符串池中,不幸的是它会修改字符串池。因为这与String
不是同一个s
对象,所以表达式的结果是false
。因此,上面的表达式将正确测试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
我们无法查看实习字符串的存储库,也无法获取所有实习字符串的集合。
测试,如果给定的字符串已被实现已经产生了一个很好的困境(顺便说一下测量的常见问题):测量本身可能会影响实习字符串的存储库;)
要测试,如果存储库包含给定的String,我们需要将该String与(最坏情况下)该存储库中的所有字符串进行比较 - 具有风险,JVM在我们开始比较之前实例化该引用字符串...这将返回true
虽然字符串在测试之前没有被实习;)
但除此之外,我没有看到任何实际用途,知道虚拟机是否已经实现了字符串。实习很便宜,如果需要就可以实习。 (如果有实际用途,String
类将提供原生测试方法)
一般来说,你不应该检查 - 只是intern
他们确定或不依赖实习。如果您需要实习或非实习字符串进行测试或试验,您可以制作它们:
实习:
s = someArbitraryString.intern();
非实习:
s = new String(someArbitraryString);