Java中字符串与逻辑运算符的比较
当比较两个字符串时,我被告知我们不应该使用逻辑运算符(==)。我们应该使用 String.equals(String) 进行比较。但是,我看到以下代码符合最新的 JDK(1.6_23)并打印“Hello Friend
”。我尝试四处搜寻,但找不到任何参考。这是从什么时候开始发生的?
public class StringComp{
public static void main(String args[]){
String s = "hello";
if(s=="hello"){
System.out.println("Hello Friend");
}else{
System.out.println("No Hello");
}
}
}
When comparing two strings, I was taught that we shouldn't use the logical operator (==). We should use String.equals(String) for the comparison. However, I see that the following code complies and prints "Hello Friend
" with the latest JDK(1.6_23). I tried searching around and couldn't find any reference. From when is this happening?
public class StringComp{
public static void main(String args[]){
String s = "hello";
if(s=="hello"){
System.out.println("Hello Friend");
}else{
System.out.println("No Hello");
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您不应该使用
==
因为它会做一些超出您想象的事情。在这种情况下,“hello”被保存(阅读字符串实习),所以它与你的stirng是同一件事是“巧合”。
==
检查两个事物是否完全相同,而不是它们是否具有相同的内容。这是一个非常大的差异,一些偶然的(尽管可以解释的)“误报”并不是使用此方法的理由。只需使用 equals 进行字符串比较即可。
从这个网站来看一个例子:
http://blog.enrii.com/2006/ 03/15/java-string-equality-common-mistake/
它返回 false,而以下代码返回 true。
You shouldn't use
==
because it does something else then you think.In this case, the "hello" is saved (Read up on string interning), so it is "coincidence" that it is the same thing as your stirng.
==
checks if two things are EXACTLY the same thing, not if they have the same content. This is a really big difference, and some accidental (though explainable) "false possitives" are no reason to use this method.Just use equals for string comparison.
From this site an example:
http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/
It returns false, while the following code returns true.
这种魔法被称为实习。
Java interns 字符串文字,因此它的计算结果很可能为 true:
The magic is called interning.
Java interns String literals and so there is a high probability that it evaluates to true:
==
运算符用于检查两者是否是对同一 String 对象的引用,而.equals
则比较值。The
==
operator is used to check if both are references to the same String object while.equals
compares the values.它适用于您的情况(据我所知,它也像早期的 JVM 中那样工作),因为
s
引用字符串文字"hello"
。用文字初始化的字符串引用指的是文字(这是后台的全局对象),而不是单独创建的新对象。正如其他人也提到的那样,这个术语是实习。因此,示例中的s
和"hello"
指的是同一个物理对象。考虑所有这些字符串都引用同一个物理对象,因此任何一对字符串之间或其中任何字符串与
"hello"
之间的 '==' 比较都会返回true
。然而,
创建了一个新对象,因此
s4 == "hello"
产生false
。It works in your case (and AFAIK it has been working like that in earlier JVMs as well) because
s
refers to the string literal"hello"
. String references initialized with literals refer to the literal (which is a global object in the background), not a separately created new object. The term for this, as others have mentioned too, is interning. Thuss
and"hello"
in your example refer to the same physical object. ConsiderAll of these strings refer to the same physical object, thus '==' comparison between any pair of these, or between any of them and
"hello"
returnstrue
.However
creates a new object, thus
s4 == "hello"
yieldsfalse
.“Java 虚拟机维护一个内部字符串引用列表(唯一字符串池),以避免堆内存中出现重复的字符串对象。每当 JVM 从类文件加载字符串文字并执行时,它都会检查该字符串是否存在于内部列表中如果它已经存在于列表中,那么它不会创建一个新的字符串,并且它使用对现有字符串对象的引用,JVM 在内部对字符串文字进行这种类型的检查,但不检查它通过“new”创建的字符串对象。 ' 关键字。您可以显式强制 JVM 对使用 String.intern() 方法通过 'new' 关键字创建的 String 对象进行这种类型的检查,这会强制 JVM 检查内部列表并使用现有的 String 对象(如果是)。 所以结论
是,JVM 在内部为 String 文字维护唯一的 String 对象,程序员不必担心 String 文字,但他们应该担心使用“new”关键字创建的 String 对象,并且应该使用 intern() 方法来避免。堆内存中的重复 String 对象反过来又提高了 java 性能。有关详细信息,请参阅以下部分。”
参考:PreciseJava.com - 字符串中的优化技术和 StringBuffer(JVM 如何使用字符串)
"Java Virtual Machine maintains an internal list of references for interned Strings ( pool of unique Strings) to avoid duplicate String objects in heap memory. Whenever the JVM loads String literal from class file and executes, it checks whether that String exists in the internal list or not. If it already exists in the list, then it does not create a new String and it uses reference to the existing String Object. JVM does this type of checking internally for String literal but not for String object which it creates through 'new' keyword. You can explicitly force JVM to do this type of checking for String objects which are created through 'new' keyword using String.intern() method. This forces JVM to check the internal list and use the existing String object if it is already present.
So the conclusion is, JVM maintains unique String objects for String literals internally. Programmers need not bother about String literals but they should bother about String objects that are created using 'new' keyword and they should use intern() method to avoid duplicate String objects in heap memory which in turn improves java performance. see the following section for more information."
Reference: PreciseJava.com - Optimization techniques in Strings and StringBuffer (How the JVM works with Strings)
==
比较对象引用您可以通过观察以下代码中的输出来理解它:
这个程序会打印
No hello
因为在这段代码中,变量
s
引用新的字符串对象,该对象又引用字符串池中的字符串文字“hello”。==
compares the object referencesYou can understand it by observing the output in the following code:
This program would print
No hello
Because in this code, the variable
s
refers to new String Object which in turn refers to String literal "hello" from the String pool.== 比较对象引用,equals() 比较字符串的值。
在您的情况下,您分配两个 String 对象,它们的值都是“hello”,然后将它们与 == 进行比较。编译器可能会决定优化并使用相同的对象引用,从而给出与您获得的结果类似的真实结果。然而,这并不能保证行为——使用 equals() 进行值比较要安全得多。
== compares the object references, equals() compares the values of the Strings.
In your case you are allocating two String objects both with value "hello", then comparing them with ==. The compiler may decide to optimise and use the same object reference, giving a true result like the one you got. However this is not guaranteed behaviour - it is much safer to use equals() for value comparison.