假设我有2个字符串ImagePopup
和a="ABC"
,我相信只会创建一个字符串,这两个字符串引用都将指向字符串常量池中的实例。在这种情况下,为什么我们需要b="ABC"
方法进行比较。请澄清。
答案 0 :(得分:1)
我相信只会创建一个字符串,这两个字符串引用都将指向字符串常量池中的实例。
关闭。 "常数池"实际上是指类文件表示中的一个部分,它包含除字符串之外的其他内容。
您的" ABC"字符串对象在运行时保存,根据Java规范没有名称。 Javadoc只是将它称为"字符串池",而JLS根本没有明确提及它。此外,此池还可能包含由在运行时调用String::intern
的应用程序代码创建的字符串。
为什么我们需要.equals()方法进行比较?
因为大多数字符串对象不是通过调用String::intern
创建的。
只有由类加载器实例化的字符串对象(因为它们代表源代码中的文字)或调用String::intern
的应用程序代码才会在池中。
如果你不知道(肯定)你正在比较的两个字符串已被实习,那么你不能确定==
会给出正确的答案。因此,测试两个字符串是否相等的安全方法是使用String::equals
。
(脚注:G1垃圾收集器也可以做一些称为&#34;字符串重复数据删除&#34;(见JEP 192)但这是一个不同的实习过程,不会改变<字符串对象的em> identity 。因此与此问题无关。)
答案 1 :(得分:0)
对于容量有限的所有类型的池或缓存,这基本相同 - 不能假设池的内容是恒定的并且永远不会改变。
在任何地方都可能会创建大量其他字符串,并且在达到容量时,池可能会随意逐出项目。
其他组件可能仍会创建具有完全相同内容的新字符串(new String(byte [])),您无法控制并可能最终进行比较。
答案 2 :(得分:0)
来自java.lang.String#equals()
的JDK8实现:
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
请注意,实现首先检查this
和anObject
的身份。这是这种依赖于实现的优化的正确位置。您的代码不应该依赖于这样的假设,因为String#equals()
会为您执行此操作。