我想澄清一下我是否理解正确:
== 是引用比较,即两个对象都指向同一个内存位置
.equals() 计算对象中值的比较
.equals()
视为有意义的等价
一般来说,您的问题的答案是“是”,但是......
.equals(...) 只会比较它所写的比较,不多也不少。
如果一个类没有重写 equals 方法,那么它默认为最近的父类重写了该方法的 equals(Object o) 方法。
如果没有父类提供覆盖,则默认为最终父类 Object 中的方法,因此您只剩下 Object#equals(Object o) 方法。根据 Object API,这与 ==; 相同。也就是说,当且仅当两个变量都引用同一个对象时,如果它们的引用是一个且相同的,它才返回 true。因此,您将测试对象相等而不是功能相等。
如果您覆盖 equals ,请务必记住覆盖 hashCode 以免“违反合同”。根据 API,如果两个对象的 equals 方法表明它们是等效的,则从 hashCode() 方法返回的结果必须相同。反过来不一定是真的。
关于 String 类:
equals() 方法比较 String 实例(在堆上)内的“值”,而不管两个对象引用是否引用同一个 String 实例。如果任何两个 String 类型的对象引用引用同一个 String 实例,那就太好了!如果这两个对象引用引用了两个不同的 String 实例......它没有任何区别。它是每个被比较的 String 实例中的“值”(即:字符数组的内容)。
另一方面,“==”运算符比较两个对象引用的值,以查看它们是否引用同一个 String 实例。如果两个对象的值引用“引用”同一个 String 实例,那么布尔表达式的结果将是“true”..duh。另一方面,如果两个对象引用的值“引用”不同的 String 实例(即使两个 String 实例具有相同的“值”,即每个 String 实例的字符数组的内容相同),则布尔表达式的结果将是“假”。
与任何解释一样,让它沉入其中。
我希望这能澄清一点。
String
,==
也是引用等于,是的,但它通常有效(如在两个具有相同内容的 String
将通常彼此==
),因为Java如何处理String
。并非总是如此,这肯定是不好的做法,但这是一个常见的错误,尤其是来自其他语言的人。
String
从字符串文字构建将被添加到名为 String constant pool
的内容中,例如 String s1 = "someString"; String s2 = "someString;"
和 s1
和s2
将共享相同的引用。 s1 == s2
将返回 true。但是如果它们是通过 String constructor
构造的,例如 String s1 = new String("someString"); String s2 = new String("someString");
,那么它们将不会共享相同的引用。 s1 == s2
将返回 false。
取决于您是在谈论“原始”还是“对象类型”,存在一些小的差异;如果您谈论的是“静态”或“非静态”成员,也可以这样说;你也可以混合以上所有...
这是一个示例(您可以运行它):
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 之间的区别让我困惑了一段时间,直到我决定仔细研究一下。他们中的许多人说,为了比较字符串,您应该使用 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
请比较上面的程序并尝试考虑一下。
好的。现在这可能会有所帮助(请阅读:print the address of object - 不可能,但我们仍然可以使用它。)
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 打印了这个(you can check the code here):
false
true
true
false
mango mango
false
true
17225372
17225372
5433634
哦!现在你看到 identityHashCode(mango) 等于 identityHashCode(mango2) 但它不等于 identityHashCode(mango3)
即使所有字符串变量(mango、mango2 和 mango3)都具有 相同 值,即“mango”,但 identityHashCode()
仍然不一样。
现在尝试取消注释这行 // mango2 = "mang";
并再次运行它,这次您将看到所有三个 identityHashCode()
都不同。嗯,这是一个有用的提示
我们知道如果 hashcode(x)=N
和 hashcode(y)=N
=> x is equal to 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
创建为新的 String 对象,而是直接引用了 "mango"
?
== 运算符测试两个变量是否具有相同的引用(也就是指向内存地址的指针)。
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() 方法测试两个变量是否引用具有相同状态(值)的对象。
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()
是方法。
运算符一般用于primitive类型比较,因此==
用于内存地址比较,equals()
方法用于比较objects。
如果您不覆盖 .equals(),则 == 和 .equals() 都指向同一个对象。
覆盖 .equals() 后,它是您想要做的事情。您可以将调用对象的状态与传入的对象状态进行比较,或者您可以调用 super.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(...)
必须由您尝试比较的类实现。否则,没有什么意义。 Object 类的方法版本与比较操作执行相同的操作:Object#equals。
您真正想要对对象使用比较运算符的唯一一次是您正在比较枚举。这是因为一次只有一个 Enum 值的实例。例如,给定枚举
enum FooEnum {A, B, C}
您一次不会有多个 A
实例,对于 B
和 C
也是如此。这意味着您实际上可以编写如下方法:
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
你不会有任何问题。
以下是 relational operator ==
和 the method .equals()
之间区别的一般规则。
object1 == object2
比较 object1 和 object2 引用的对象是否引用了堆中的同一内存位置。
object1.equals(object2)
比较 object1 和 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
此字符串比较可用作比较其他类型对象的基础。
例如,如果我有一个 Person 类,我需要定义比较两个人的标准。假设这个人类有身高和体重的实例变量。
因此,创建人员对象 person1 and person2
并使用 .equals()
比较这两个对象,我需要重写人员类的 equals 方法 来定义比较将基于哪些实例变量(身高或体重)是。
但是,== operator will still return results based on the memory location of the two objects(person1 and 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(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
*/
== 和 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
另请注意,.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 对象都包含相同的数据,但引用不一样,所以 equals 返回 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)的基础上比较对象
但是==
仍然比较对象的引用。
示例 1 -
== 和 .equals 方法都仅供参考比较。这意味着两个对象是否引用同一个对象。
Object class equals method implementation
public class HelloWorld{
public static void main(String []args){
Object ob1 = new Object();
Object ob2 = ob1;
System.out.println(ob1 == ob2); // true
System.out.println(ob1.equals(ob2)); // true
}
}
https://i.stack.imgur.com/Nbha6.png
示例 2 -
但是如果我们想使用 equals 方法比较对象的内容,那么类必须重写对象的类 equals() 方法并提供内容比较的实现。在这里,String 类重写了用于内容比较的 equals 方法。所有包装类都覆盖了用于内容比较的 equals 方法。
String class equals method implementation
public class HelloWorld{
public static void main(String []args){
String ob1 = new String("Hi");
String ob2 = new String("Hi");
System.out.println(ob1 == ob2); // false (Both references are referring two different objects)
System.out.println(ob1.equals(ob2)); // true
}
}
https://i.stack.imgur.com/HPVXk.png
示例 3 -
对于字符串,还有一个用例。在这里,当我们将任何字符串分配给字符串引用时,就会在字符串常量池中创建字符串常量。如果我们将相同的字符串分配给新的字符串引用,则不会创建新的字符串常量,而是引用现有的字符串常量。
public class HelloWorld{
public static void main(String []args){
String ob1 = "Hi";
String ob2 = "Hi";
System.out.println(ob1 == ob2); // true
System.out.println(ob1.equals(ob2)); // true
}
}
https://i.stack.imgur.com/wIglp.png
请注意,每当重写该方法时,通常都需要重写 hashCode 方法,以维护 hashCode 方法的一般约定,即相等的对象必须具有相等的哈希码。
Java API equals() method contract
==
可用于许多对象类型,但您可以将 Object.equals
用于任何类型,尤其是字符串和 Google 地图标记。
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");
}
}
}
----输出----- true false true
值得补充的是,对于原始类型(即 Int、Long、Double)的包装器对象,如果两个值相等, == 将返回 true。
Long a = 10L;
Long b = 10L;
if (a == b) {
System.out.println("Wrapped primitives behave like values");
}
相比之下,将上述两个 Long 放入两个单独的 ArrayList 中,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.");
Long a = 128l; Long b = 128l; System.out.println(a == b);
String pool(又名 interning)和 Integer pool 进一步模糊了区别,并且在某些情况下可能允许您将 ==
用于对象而不是 .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;
我建议您远离这种微优化,并且始终将 .equals
用于对象,将 ==
用于基元:
assert (new String("a")).equals(new String("a"));
Integer i = 128;
Integer j = 128;
assert i.equals(j);
简而言之,答案是“是”。
在 Java 中,==
运算符比较两个对象以查看它们是否指向相同的内存位置;而 .equals()
方法实际上比较两个对象以查看它们是否具有相同的对象值。
这是同一性和等价性之间的区别。
a == b
表示 a 和 b 相同,也就是说,它们是内存中相同对象的符号。
a.equals( b )
表示它们是等价的,它们是在某种意义上具有相同值的对象的符号——尽管这些对象可能在内存中占据不同的位置。
请注意,对于等价,如何评估和比较对象的问题开始发挥作用——复杂的对象在实际用途中可能被认为是等价的,即使它们的某些内容不同。有了身份,就不存在这样的问题。
由于 Java 不支持运算符重载,因此 ==
对于每个对象的行为都相同,但 equals()
是方法,它可以在 Java 中被覆盖,并且可以根据业务规则更改比较对象的逻辑。
Java 中 ==
和 equals 的主要区别在于 "=="
用于比较基元,而 equals()
方法建议用于检查对象的相等性。
字符串比较是同时使用 ==
和 equals()
方法的常见场景。 由于 java.lang.String 类覆盖 equals 方法,如果两个 String 对象包含相同的内容但 ==
只有当两个引用指向同一个对象时才会返回 true。
这是一个示例,使用 ==
和 equals()
方法比较 Java 中的两个字符串是否相等,这将消除一些疑问:
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);
}
}
equals() 方法主要比较对象的原始内容。
如果我们写
String s1 = "Samim";
String s2 = "Samim";
String s3 = new String("Samim");
String s4 = new String("Samim");
System.out.println(s1.equals(s2));
System.out.println(s2.equals(s3));
System.out.println(s3.equals(s4));
输出将是
true
true
true
因为 equals() 方法比较对象的内容。在第一个 System.out.println() 中,s1 和 s2 的内容是相同的,这就是它打印为真的原因。其他两个 System.out.println() 也是如此。
再次 ,
String s1 = "Samim";
String s2 = "Samim";
String s3 = new String("Samim");
String s4 = new String("Samim");
System.out.println(s1 == s2);
System.out.println(s2 == s3);
System.out.println(s3 == s4);
输出将是
true
false
false
因为 == 运算符主要比较对象的引用而不是值。在第一个 System.out.println() 中,s1 和 s2 的引用相同,这就是它返回 true 的原因。
在第二个 System.out.println() 中,创建了 s3 对象,这就是为什么会创建另一个 s3 引用,并且 s2 和 s3 的引用会有所不同,因此它返回“false”。
第三个 System.out.println(),遵循第二个 System.out.println() 的规则,所以它会返回“false”。
基本上,==
比较两个对象是否在堆上具有相同的引用,因此除非两个引用链接到同一个对象,否则这种比较将是错误的。
equals()
是从 Object
类继承的方法。默认情况下,此方法比较两个对象是否具有相同的引用。它的意思是:
object1.equals(object2)
<=> object1 == object2
然而,如果你想在同一个类的两个对象之间建立相等性,你应该重写这个方法。如果您已覆盖 equals()
,则覆盖方法 hashCode()
也非常重要。
在建立相等性时实施 hashCode()
是 Java 对象契约的一部分。如果您正在使用集合,但尚未实现 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()
评估对象中值的比较。
不定期副业成功案例分享
==
检查内存引用,那么为什么我会在 [this][1][1] 中出现这种奇怪的行为:docs.google.com/document/d/… 我希望输出为真。可以清除我的困惑The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
<br/>Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
(docs.oracle.com/javase/7/docs/api/java/lang/…)