到目前为止,我一直在程序中使用==运算符来比较所有的字符串。 然而,我遇到了一个错误,将其中一个改为.equals(),它修复了这个错误。

==不好吗?什么时候应该使用,什么时候不应该使用?有什么不同?


当前回答

在Java中,当使用==运算符比较两个对象时,它会检查两个对象是否指向内存中的相同位置。换句话说,它检查两个对象名称是否基本上引用了相同的内存位置。

Java String类实际上重写了Object类中的默认equals()实现——它重写了该方法,以便它只检查字符串的值,而不检查它们在内存中的位置。 这意味着如果调用equals()方法来比较两个String对象,那么只要实际的字符序列相等,两个对象就被认为是相等的。

==操作符检查两个字符串是否完全相同的对象。

equals()方法检查两个字符串是否具有相同的值。

其他回答

我同意zacherates的回答。

但是你能做的是在非文字字符串上调用intern()。

来自zacherates的例子:

// ... but they are not the same object
new String("test") == "test" ==> false 

如果你实习非文字字符串相等为真:

new String("test").intern() == "test" ==> true 

==操作符检查两个字符串是否完全相同的对象。

equals()方法将检查两个字符串是否具有相同的值。

Java有一个String池,Java在该池下管理String对象的内存分配。参见Java中的字符串池

当您使用==操作符检查(比较)两个对象时,它将地址相等性比较到字符串池中。如果两个String对象具有相同的地址引用,则返回true,否则返回false。但是如果你想比较两个String对象的内容,那么你必须重写equals方法。

equals实际上是Object类的方法,但它被重写到String类中,并给出了一个比较Object内容的新定义。

Example:
    stringObjectOne.equals(stringObjectTwo);

但注意,它尊重String的情况。如果你想要不区分大小写的比较,那么你必须使用String类的equalsIgnoreCase方法。

让我们来看看:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE

是的,很糟糕……

==表示两个字符串引用是完全相同的对象。您可能听说过这种情况,因为Java保留了某种文字表(它确实如此),但情况并非总是如此。一些字符串以不同的方式加载,从其他字符串构造,等等,所以永远不要假设两个相同的字符串存储在相同的位置。

Equals为你做真正的比较。

==测试引用是否相等(它们是否是同一个对象)。

.equals()测试值是否相等(它们是否包含相同的数据)。

Objects.equals()在调用.equals()之前检查是否为空,因此不必这样做(在JDK7中可用,在Guava中也可用)。

因此,如果你想测试两个字符串是否具有相同的值,你可能会使用Objects.equals()。

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

你几乎总是想使用Objects.equals()。在极少数情况下,您知道您正在处理的是实习字符串,您可以使用==。

来自JLS 3.10.5。字符串:

而且,string字面值总是引用string类的同一个实例。这是因为字符串字面量——或者更一般地说,是常量表达式的值的字符串(§15.28)——被“internned”,以便使用string .intern方法共享唯一的实例。

在JLS 3.10.5-1中也可以找到类似的例子。

其他需要考虑的方法

String.equalsIgnoreCase()忽略大小写的值相等性。但是要注意,在各种与区域设置相关的情况下,此方法可能会产生意想不到的结果,请参阅这个问题。

String. contentequals()将String的内容与任何CharSequence的内容进行比较(自Java 1.5起可用)。在进行相等比较之前,不必将StringBuffer等转换为String,但将null检查留给您。