Java中的== vs equals()有什么区别?
我想澄清,如果我正确地理解这一点:
-
==
– >是参考比较,即两个对象指向相同的内存位置 -
.equals()
– >计算对象中值的比较
我的理解是否正确?
一般来说,你的问题的答案是“是”,但是…
- 等于只比较它所写的比较,不多也不less。
- 如果一个类没有重写equals方法,那么它默认为已经重写了这个方法的最接近父类的
equals(Object o)
方法。 - 如果没有父类提供覆盖,则默认为来自最终父类Object的方法,因此剩下
Object#equals(Object o)
方法。 根据对象API,这与==
相同; 也就是说, 当且仅当两个variables引用相同的对象时,它们才返回true,如果它们的引用是相同的。 因此,你将testing对象的平等,而不是function的平等 。 - 一定要记住重写
hashCode
以覆盖equals
以免“破坏合约”。 根据API,从两个对象的hashCode()
方法返回的结果必须是相同的,如果它们的equals
方法显示它们是等价的。 反过来不一定是对的。
对于String类:
equals() 方法比较String实例(堆中)的“value”,而不pipe这两个对象引用是否引用相同的String实例。 如果任何两个Stringtypes的对象引用指向相同的String实例,那么太棒了! 如果这两个对象引用引用了两个不同的String实例,则不会有所作为。 它是每个正在比较的string实例中的“值”(即:字符数组的内容)。
另一方面,“==” 运算符比较两个对象引用的值,以查看它们是否引用相同的String实例 。 如果两个对象引用的值“引用”相同的string实例,那么布尔expression式的结果将是“真正的”.. duh。 另一方面,如果两个对象引用的值“引用” 不同的String实例 (即使两个String实例具有相同的“值”,即每个String实例的字符数组的内容相同),布尔expression式的结果将是“false”。
就像任何解释一样,让它沉入其中。
我希望这个清理一下。
根据您是在谈论“基元”还是“对象types”,有一些细微的差异。 如果你在谈论“静态”或“非静态”成员,也可以这样说; 你也可以混合以上所有…
这里是一个例子(你可以运行它):
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类中的方法)的解释:
- ==: http : //docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
- .equals(…): http ://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object )
==和equals之间的区别让我困惑了一段时间,直到我决定仔细看看它。 他们中的许多人说,比较string,你应该使用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
哦! 现在你看到identityHashCode(mango)等于identityHashCode(mango2)但是它不等于identityHashCode(mango3)
即使所有的stringvariables – 芒果,芒果2和芒果3具有相同的值“芒果”。 但是identityHashCode()
仍然是不一样的。
现在尝试取消这一行的注释// mango2 = "mang";
并再次运行它,这次你会看到所有三个identityHashCode()
是不同的。 嗯,这是一个有用的提示
我们知道如果hashcode(x)=N
且hashcode(y)=N
=> x is equal to y
我不知道java如何在内部工作,但我认为这是发生在我说:
mango = "mango";
java创build了一个string"mango"
,并被variablesmango
指出(引用)这样的东西
mango ----> "mango"
现在在接下来的一行中,我说:
mango2 = "mango";
它实际上重用了这个看起来像这样的string"mango"
mango ----> "mango" <---- mango2
当我说时,芒果和芒果都指向相同的参考
mango3 = new String("mango")
它实际上为“芒果”创build了一个全新的参考(string)。 看起来像这样,
mango -----> "mango" <------ mango2 mango3 ------> "mango"
这就是为什么当我输出的mango == mango2
的价值,它输出true
。 当我输出了mango3 == mango2
的值时,它输出了false
(即使值相同)。
而当你取消注释行// mango2 = "mang";
它实际上创build了一个string“mang”,它把我们的graphics变成这样:
mango ---->"mango" mango2 ----> "mang" mango3 -----> "mango"
这就是为什么identityHashCode对所有人都不一样。
希望这可以帮助你们。 其实我想生成一个testing用例==失败和等于()通过。 请随时发表评论,让我知道如果我错了。
==运算符testing两个variables是否具有相同的引用(又名指向内存地址的指针) 。
String foo = new String("abc"); String bar = new String("abc"); if(foo==bar) // False (The objects are not the same) bar = foo; if(foo==bar) // True (Now the objects are the same)
而equals()方法testing两个variables是否引用具有相同状态(值)的对象 。
String foo = new String("abc"); String bar = new String("abc"); if(foo.equals(bar)) // True (The objects are identical but not same)
干杯:-)
您将不得不重写equals函数(以及其他函数)以将其与自定义类一起使用。
equals方法比较对象。
==
二元运算符比较内存地址。
如果您不覆盖.equals(),则==和.equals()指向相同的对象。
一旦你覆盖.equals(),你希望你想做什么。 您可以将调用对象的状态与传入的对象状态进行比较,也可以调用super.equals()
“==”是一个运算符,“equals”是一个方法。 运算符用于原始types比较,因此“==”用于内存地址比较,“equals”方法用于比较对象。
请记住, .equals(...)
必须由您正在比较的类实现。 否则,没有太大的意义。 Object类的方法的版本与比较操作完全相同: Object#equals 。
唯一一次你真的想使用比较运算符的对象是你正在比较枚举。 这是因为一次只有一个Enum值的实例。 例如,给出枚举
enum FooEnum {A, B, C}
你一次不会有一个以上的A
实例, B
和C
也是一样的。 这意味着你可以写一个像这样的方法:
public boolean compareFoos(FooEnum x, FooEnum y) { return (x == y); }
而且你将没有任何问题。
==运算符:
==是Java中的一个关系运算符,用于比较两个操作数。 它用于确定两个操作数是否相等。 使用==运算符,可以比较任何基本types,如int,char,float和Booleans。 比较之后,==运算符返回一个布尔值。 如果两个操作数相等,则==运算符返回一个真值。 但是,如果两个操作数不相等,则返回一个假值。 当与对象一起使用时,==运算符会比较两个对象引用,并确定它们是否引用同一个实例。
.equals()方法
equals()是String类中可用的方法,用于比较两个string并确定它们是否相等。 作为比较的结果,此方法返回一个布尔值。 如果两个string按相同的顺序包含相同的字符,则equals()方法返回true。 否则,它返回一个错误的值。
例如:
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(Object o)比较实例的hashCode()。 这就是为什么说如果你稍后没有遇到意外,不要打破equals()和hashCode()之间的契约。
String s1 = new String("Ali"); String s2 = new String("Veli"); String s3 = new String("Ali"); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); System.out.println("(s1==s2):" + (s1 == s2)); System.out.println("(s1==s3):" + (s1 == s3)); System.out.println("s1.equals(s2):" + (s1.equals(s2))); System.out.println("s1.equal(s3):" + (s1.equals(s3))); /*Output 96670 3615852 96670 (s1==s2):false (s1==s3):false s1.equals(s2):false s1.equal(s3):true */
==
可以在许多对象types中使用,但是您可以使用Object.equals
作为任何types,特别是Strings和Google Map Markers。
还要注意.equals()
通常包含==
用于testing,因为如果要testing两个对象是否相等,这是您希望testing的第一件事。
而==
实际上是看原始types的值,对于它检查引用的对象。
==运算符总是参考比较。 但是如果
equals()方法
如果我们被重写的equals方法,它的实现取决于在重写的方法中给出的实现的基本比较对象。
class A { int id; String str; public A(int id,String str) { this.id=id; this.str=str; } public static void main(String arg[]) { A obj=new A(101,"sam"); A obj1=new A(101,"sam"); obj.equals(obj1)//fasle obj==obj1 // fasle } }
在上面的代码中,obj和obj1对象都包含相同的数据,但引用不相同,所以等于返回false和==。 但如果我们重写equals方法比
class A { int id; String str; public A(int id,String str) { this.id=id; this.str=str; } public boolean equals(Object obj) { A a1=(A)obj; return this.id==a1.id; } public static void main(String arg[]) { A obj=new A(101,"sam"); A obj1=new A(101,"sam"); obj.equals(obj1)//true obj==obj1 // fasle } }
知道检查它将返回true和false为相同的情况下,只有我们重写
等于方法。
它比较对象的基本内容(id)的对象
但==
仍然比较对象的引用。
public class StringPool { public static void main(String[] args) { String s1 = "Cat";// will create reference in string pool of heap memory String s2 = "Cat"; String s3 = new String("Cat");//will create a object in heap memory // Using == will give us true because same reference in string pool if (s1 == s2) { System.out.println("true"); } else { System.out.println("false"); } // Using == with reference and Object will give us False if (s1 == s3) { System.out.println("true"); } else { System.out.println("false"); } // Using .equals method which refers to value if (s1.equals(s3)) { System.out.println("true"); } else { System.out.println("False"); } } }
—-输出—–真假假
可能值得添加的是,对于原始types的包装器对象(即Int,Long,Double – ==)将返回true,如果两个值相等。
Long a = 10L; Long b = 10L; if (a == b) { System.out.println("Wrapped primitives behave like values"); }
相比之下,将上述两个Long分成两个独立的ArrayLists,equals将它们视为相同,但==不会。
ArrayList<Long> c = new ArrayList<>(); ArrayList<Long> d = new ArrayList<>(); c.add(a); d.add(b); if (c == d) System.out.println("No way!"); if (c.equals(d)) System.out.println("Yes, this is true.");
由于Java不支持运算符重载,所以==对于每个对象都是相同的,但equals()是方法,可以在Java中重写,并且逻辑比较对象可以根据业务规则进行更改。
Java中的==和equals的主要区别在于“==”用于比较原语,而build议使用equals()方法检查对象是否相等。
string比较是使用==和equals方法的常见scheme。 由于java.lang.String类覆盖了equals方法,所以如果两个String对象包含相同的内容,则返回true,但如果两个引用指向同一个对象,==将只返回true。
下面是使用==和equals()方法比较Java中两个string是否相等的示例 ,它将清除一些疑问:
public class TEstT{ public static void main(String[] args) { String text1 = new String("apple"); String text2 = new String("apple"); //since two strings are different object result should be false boolean result = text1 == text2; System.out.println("Comparing two strings with == operator: " + result); //since strings contains same content , equals() should return true result = text1.equals(text2); System.out.println("Comparing two Strings with same content using equals method: " + result); text2 = text1; //since both text2 and text1d reference variable are pointing to same object //"==" should return true result = (text1 == text2); System.out.println("Comparing two reference pointing to same String with == operator: " + result); } }
string池 (又名interning )和整数池进一步模糊了区别,并且可能允许您在某些情况下使用==
而不是.equals
这可以给你更大的性能(?),但代价是更复杂。
例如:
assert "ab" == "a" + "b"; Integer i = 1; Integer j = i; assert i == j;
复杂性权衡:以下可能会让你感到惊讶:
assert new String("a") != new String("a"); Integer i = 128; Integer j = 128; assert i != j;
我build议你远离这样的微观优化, 总是使用.equals
作为对象, ==
对于原语:
assert (new String("a")).equals(new String("a")); Integer i = 128; Integer j = 128; assert i.equals(j);
基本上, ==
比较两个对象是否在堆上具有相同的引用,所以除非两个引用链接到同一个对象,否则这个比较将是错误的。
equals()
是从Object
类inheritance的方法。 这个方法默认比较两个对象是否具有相同的引用。 它的意思是:
object1.equals(object2)
<=> object1 == object2
但是,如果要在同一个类的两个对象之间build立平等,则应该重写此方法。 如果覆盖equals()
,重写hashCode()
方法也很重要。
当build立相等时,实现hashCode()
是Java Object Contract的一部分。 如果你正在使用集合,并且你还没有实现hashCode()
,奇怪的坏事情可能会发生:
HashMap<Cat, String> cats = new HashMap<>(); Cat cat = new Cat("molly"); cats.put(cat, "This is a cool cat"); System.out.println(cats.get(new Cat("molly"));
如果你还没有实现hashCode()
那么在执行前面的代码之后将会打印null
。
==和equals()之间的主要区别是
1)==用于比较原语。
例如 :
String string1 = "Ravi"; String string2 = "Ravi"; String string3 = new String("Ravi"); String string4 = new String("Prakash"); System.out.println(string1 == string2); // true because same reference in string pool System.out.println(string1 == string3); // false
2)equals()用于比较对象。 例如 :
System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects System.out.println(string1.equals(string3)); // true System.out.println(string1.equals(string4)); // false
“==”实际上是比较两个对象引用,看他们是否指向同一个对象。
“等于”是一个比较实际string值的“深度比较”。