我想澄清一下,如果我理解正确的话:
==
是引用比较,即两个对象指向同一内存位置.equals()
则比较对象中的值
我想澄清一下,如果我理解正确的话:
==
是引用比较,即两个对象指向同一内存位置.equals()
则比较对象中的值一般而言,对于你的问题,答案是“是”,但是...
.equals(...)
方法只会比较它所指定的内容,不多不少。equals(Object o)
方法。Object#equals(Object o)
方法。根据Object API,这与==
相同;也就是说,它仅在两个变量引用同一个对象时返回true。因此,您将测试对象相等性而不是功能相等性。equals
时覆盖hashCode
,以免“违反契约”。根据API,对于equals
方法显示它们等效的两个对象,hashCode()
方法返回的结果必须相同。反之则不一定成立。==
检查内存引用,那么为什么我在[这里][1]得到了奇怪的行为:https://docs.google.com/document/d/1ducE-yZEDyyjoKUTkTEsw3sdSw740d0Z5iiJz3IzABE/edit?usp=sharing 我期望的输出是 true。请帮我澄清疑惑。 - JPG关于 String 类:
equals() 方法 比较堆中 String 实例内部的 "value",无论两个对象引用是否指向同一个 String 实例。如果任意两个类型为 String 的对象引用指向同一个 String 实例,则非常好!如果两个对象引用指向两个不同的 String 实例... 这并没有什么区别。被比较的是每个 String 实例内部的 "value"(也就是字符数组的内容)。
另一方面,"==" 运算符 比较 两个对象引用 的值,以确定它们是否引用同一个 String 实例。 如果这两个对象引用的值都“引用”同一个 String 实例,那么布尔表达式的结果将是“true”...显然。 如果,另一方面,这两个对象引用的值都“引用”不同的 String 实例(即使这两个 String 实例具有相同的“value”,也就是每个 String 实例的字符数组内容相同),布尔表达式的结果将是“false”。
就像任何解释一样,请理解一下。
希望这能让事情更加清晰明了。
String
类型,==
也是引用相等的,但通常情况下它会起作用(例如两个具有相同内容的String
通常会相互==
),因为Java如何处理String
。它并不总是有效的,而且这肯定是一种不好的做法,但这是一个常见的错误,特别是来自其他语言的人。 - TonioString
将被添加到称为String常量池
的东西中,例如 String s1 = "someString"; String s2 = "someString;"
,s1
和s2
将共享相同的引用。s1 == s2
将返回true。但是,如果它们是通过String构造函数
构造的,例如String s1 = new String("someString"); String s2 = new String("someString");
,则它们将不共享相同的引用。s1 == s2
将返回false。 - Gavin如果你在讨论“原始类型”或“对象类型”,那么有一些小差异;同样,如果你在讨论“静态”或“非静态”成员,也可以这样说;你还可以混合上述所有内容...
这里有一个例子(你可以运行它):
public final class MyEqualityTest
{
public static void main( String args[] )
{
String s1 = new String( "Test" );
String s2 = new String( "Test" );
System.out.println( "\n1 - PRIMITIVES ");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals( s2 )); // true
A a1 = new A();
A a2 = new A();
System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
System.out.println( a1 == a2 ); // false
System.out.println( a1.s == a2.s ); // true
System.out.println( a1.s.equals( a2.s ) ); // true
B b1 = new B();
B b2 = new B();
System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
System.out.println( b1 == b2 ); // false
System.out.println( b1.getS() == b2.getS() ); // false
System.out.println( b1.getS().equals( b2.getS() ) ); // true
}
}
final class A
{
// static
public static String s;
A()
{
this.s = new String( "aTest" );
}
}
final class B
{
private String s;
B()
{
this.s = new String( "aTest" );
}
public String getS()
{
return s;
}
}
你可以通过这些链接比较"=="(等号操作符)和".equals(...)"(java.lang.Object类中的方法)的解释:
==
和equals
之间的区别让我困惑了一段时间,直到我决定仔细研究它。很多人说比较字符串应该使用equals
而不是==
。希望在这个答案中我能够说明两者的差异。String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);
如果你说,
false
true
我觉得你是正确的,但是你为什么这样说呢? 如果你说输出结果为,
true
false
我会说你是错误的,但我还是会问你,为什么你认为那是正确的?
好的,让我们尝试回答这个问题:
以下程序的输出是什么:
String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);
现在,如果你说:
false
true
我会说你是错误的,但是为什么现在它是错误的呢?这个程序的正确输出是:
true
false
请比较上述程序并思考。
好的。现在这可能会有所帮助(请阅读此内容:打印对象地址 - 虽然不可能,但我们仍然可以使用它)。
String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));
你能试着想一想上面代码中最后三行的输出结果吗? 对于我来说,ideone打印出了这个结果(你可以在这里检查代码):
false
true
true
false
mango mango
false
true
17225372
17225372
5433634
哦!现在你看到了mango和mango2的identityHashCode()值相等,但它与mango3的不同。
尽管所有字符串变量——mango、mango2和mango3——都具有相同的值,即“mango”,但identityHashCode()
仍然不是所有变量的相同。
现在试着取消注释这行代码 // mango2 = "mang";
然后再次运行程序,你会发现所有三个identityHashCode()
都不同。嗯,这是一个有用的提示。
我们知道如果hashcode(x) = N
且hashcode(y) = N
=> x = y
我不确定Java内部是如何工作的,但我认为这就是当我说:
mango = "mango";
Java创建了一个字符串"mango"
,并且这个字符串被一个变量mango
所引用。
mango ----> "mango"
现在,在下一行中,我说:
mango2 = "mango";
实际上,它重复使用了相同的字符串"mango"
,看起来像这样。
mango ----> "mango" <---- mango2
两个变量mango和mango2指向同一个引用。 现在,当我说:
mango3 = new String("mango")
它实际上为“mango”创建了一个全新的引用(字符串),大致看起来是这样的:
mango -----> "mango" <------ mango2
mango3 ------> "mango"
因此,当我输出mango == mango2
的值时,它输出了true
。而当我输出mango3 == mango2
的值时,尽管两个变量的值相同,但它输出了false
。
当你取消注释// mango2 = "mang";
这行时,它实际上创建了一个字符串"mang",并将我们的图形变成了这样:
mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
这就是为什么identityHashCode不会对所有对象都相同。
希望这能对你们有所帮助。
事实上,我想生成一个测试用例,其中==
失败,但equals()
成功。
请随时评论并让我知道如果我错了。
mango == mango2
发生的原因是因为你没有将 mango2
创建为一个新的字符串对象,而是直接引用了 "mango"
。 - brtString foo = new String("abc");
String bar = new String("abc");
if(foo==bar)
// False (objects are identical but not same)
bar = foo;
if(foo==bar)
// True (Now, objects are identical and same)
String foo = new String("abc");
String bar = new String("abc");
if(foo.equals(bar))
// True (The objects are identical but not same)
==
是一个运算符,equals()
是一个方法。
运算符通常用于比较原始类型,因此==
用于内存地址比较,而equals()
方法用于比较对象。
String w1 ="Sarat";
String w2 ="Sarat";
String w3 = new String("Sarat");
System.out.println(w1.hashCode()); //3254818
System.out.println(w2.hashCode()); //3254818
System.out.println(w3.hashCode()); //3254818
System.out.println(System.identityHashCode(w1)); //prints 705927765
System.out.println(System.identityHashCode(w2)); //prints 705927765
System.out.println(System.identityHashCode(w3)); //prints 366712642
if(w1==w2) // (705927765==705927765)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
if(w2==w3) // (705927765==366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints false
if(w2.equals(w3)) // (Content of 705927765== Content of 366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
如果你没有重写.equals()方法,那么==和.equals()都指向同一个对象。
一旦你重写了.equals()方法,你可以根据需要比较调用对象的状态和传递对象的状态,或者只需调用super.equals()。
以下是区分关系运算符==
和.equals()方法
的一般性规则。
object1 == object2
比较的是object1和object2指向的内存中是否为同一地址。
object1.equals(object2)
比较的是不考虑它们在内存中的位置,而是比较它们的值。
可以使用String来很好地演示这一点。
情况1
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? false
is str1.equals(str2) ? true
场景2
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? true
is str1.equals(str2) ? true
这种字符串比较可以作为比较其他类型对象的基础。
例如,如果我有一个人类,我需要定义用于比较两个人的标准。假设这个人类具有身高和体重的实例变量。
因此,创建人物对象person1和person2
,并使用.equals()
比较这两个人时,我需要覆盖person class的equals方法,以定义基于哪些实例变量(身高或体重)进行比较。
但是,==运算符仍将返回基于两个对象(person1和person2)的内存位置的结果
。
为了方便通用化比较该人物对象,我创建了以下测试类。对这些概念进行实验将揭示大量事实。
package com.tadtab.CS5044;
public class Person {
private double height;
private double weight;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(height);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
/**
* This method uses the height as a means of comparing person objects.
* NOTE: weight is not part of the comparison criteria
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
return false;
return true;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.setHeight(5.50);
person1.setWeight(140.00);
Person person2 = new Person();
person2.setHeight(5.70);
person2.setWeight(160.00);
Person person3 = new Person();
person3 = person2;
Person person4 = new Person();
person4.setHeight(5.70);
Person person5 = new Person();
person5.setWeight(160.00);
System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
System.out.println("is person2 == person3 ? " + (person2 == person3)); // true
//this is because perosn3 and person to refer to the one person object in memory. They are aliases;
System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
// even if the person2 and person5 have the same weight, they are not equal.
// it is because their height is different
System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}
}
这个类的执行结果是:
is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
.equals()
可以被理解为“有实际意义的等价”。 - vikingsteveObject.Equals()
方法。派生类,如String
,可以通过重写.Equals
方法来定义两个字符串是==的含义。Java无法这样做。JavaString
类(以及Java中的任何类)都没有覆盖==**以使其行为符合预期的方法。这意味着你必须自己手动调用.equals()
。 - Ian Boyd