Equals / equals和==运算符之间的区别?
a == b
和a.Equals(b)
什么a.Equals(b)
?
假设a
和b
的类型是参考类型:
-
在Java中,==总是会比较身份 – 即两个值是否是对同一对象的引用。 这也被称为参考平等 。 Java没有任何用户定义的运算符重载。
-
在C#中,这取决于。 除非有一个重载操作符来处理它,==将表现得像Java一样(比较引用的相等性)。 但是,如果存在与
a
和b
的编译时类型相匹配的重载(例如,如果它们都被声明为字符串),那么将调用该重载。 这可以表现得如何,但它通常实现价值平等 (即a
和b
可以指不同但相同的价值,它仍然会返回true)。
在这两种语言中, a.Equals(b)
或a.equals(b)
将调用Object
声明的虚拟Equals
/ equals
方法,除非编译时类型a
引入了更具体的重载。 这可能会或可能不会在引用的对象的执行时间类型中被重写。 在.NET和Java中, Object
的实现也检查身份。 请注意,这取决于执行时间类型,而不是重载分辨率依赖的编译时类型 。
当然,如果a
为null
那么当您尝试调用a.equals(b)
或a.Equals(b)
时,将会得到一个NullReferenceException
/ NullPointerException
a.Equals(b)
。
==运算符检查两个对象是否是完全相同的对象,这在大多数情况下是不可行的。 Equals方法将能够在内部比较两个对象
例:
class Mycar { string color; Mycar(string str) { color = str; } } Mycar a = new Mycar("blue"); Mycar b = new Mycar("blue"); a==b // Returns false a.Equals(b) // Returns true
这取决于a
和b
的类型。
尤其是, Equals
是一个虚拟的方法,所以它的行为不依赖于a和b的编译时类型。
在Java中, ==
总会按引用进行比较,这不一定是你想要的,特别是对于字符串。
在C#中, ==
可以重载,但不是虚拟的(这是一个static
方法)。 因此,如果将a
或b
声明为object
,即使它们的实际类型重载operator ==
,它也将通过引用进行比较。
此外, a.Equals(b)
将抛出一个NullReferenceException
(Java中的NullPointerException
),如果a为null
。
String a = "toto".Substring(0, 4); String b = "toto"; Object aAsObj = a; Assert.IsTrue(a.Equals(b)); Assert.IsTrue(a == b); Assert.IsFalse(aAsObj == b); Assert.IsTrue(aAsObj.Equals(b));
这个测试在.NET中传递,诀窍是Equals
是一个方法,而==
是一个static
方法,所以aAsObj == b
使用
static bool Object.operator==(object a, object b) //Reference comparison
而a == b
使用
static bool String.operator==(string a, string b) //String comparison
但是a.Equals(b)
或aAsObj.Equals(b)
总是使用:
bool String.Equals(Object obj) //String comparison
如果引用包含相同的值,则a == b
返回true,即它们指向相同的对象,或者它们都是null。
可以重写equals()
方法来比较对象。 例如,在Strings
,如果字符串包含相同的字符串,则该方法返回true
,即使它们是不同的字符串对象。 你可以用你自己的东西做类似的事情。
如果o是空引用, o.equals()
将会抛出一个异常。
==是该语言的基本操作符。 运算符==测试以查看两个对象引用变量是否引用完全相同的对象实例。
equals()是一个基本上由java.lang.Object类定义的实例方法。 方法.equals()测试是否两个对象相互比较是相同的,但是它们不需要是同一个对象的完全相同的实例。
==运算符总是给你相同的结果,但是equals()方法根据你的实现(实现的逻辑)为你提供输出。当重写equals()方法时,重写equals:“Considerations”。
1.自反:对于任何非空引用x,x.equals(x)应该返回true。
2.对称:对于任何非空引用x和y,如果x.equals(y)为true,则y.equals(x)必须返回true。
3.传递:对于任何非空引用x,y和z,如果x.equals(y)为true,则y.equals(z)为true,则x.equals(z)必须返回true。
4.一致性:对于任何非空引用x和y,x.equals(y)的多个调用始终返回true或始终返回false,而不更改为equals比较提供的信息。
5.对于任何非空引用x,x.equals(null)必须返回false。 注意:如果o1.equals(o2)为true,那么o1.hashcode()== o2.hashcode(),但是反过来可能是也可能不是真的。
例子:
整数i =新的整数(10); 整数j = i;
在上面的代码中。 我== j是真的,因为我和j指的是同一个对象。
整数i =新的整数(10); 整数j =新的整数(10);
在上面的代码中,i == j是FALSE,因为虽然它们都有值10,但它们是两个不同的对象。 但是,(j)将返回true。
使用自动装箱
整数i = 10;
整数j = 10;
Boolean b =(i == j);
System.out.println(b);
这将返回TRUE,因为整数范围-127到128之间的整数,所以在这种情况下,这两个是相同的对象(JVM不会创建一个新的对象,它会从池中检索它)。
String类重写equals方法,所以这里是equals和==的一个例子。String s1 = new String(“abc”); String s2 = new String(“abc”);
注意:字符串是在String常量池中创建的,所以当我们创建像String s =“abc”时,它将通过调用本地方法intern()来检查池,如果它没有找到任何字符串,会创建一个新的,但如果我们调用new操作符,那么它将创建一个新的String,而不管检查存在池。
public class StringEqualityTest { public static void main(String []a){ String s1=new String("abc"); String s2=new String("abc"); System.out.print("s1.equals(s2) :"+s1.equals(s2)+" s1==s2 :"); System.out.println(s1==s2); String s3="abc"; String s4="abc"; System.out.print("s3.equals(s4) :"+s1.equals(s2)+" s3==s4 :"); System.out.println(s3==s4); } }
输出:s1.equals(s2):true s1 == s2:false s3.equals(s4):true s3 == s4:true
==
使用一个对象的引用,或者如果一个整数/浮点数等,那么它比较实际的数字。 从技术上讲,它只是比较内存位置。 而.equals
使用对象类中的一个方法来比较对象,它可以覆盖你的个人类。 另外,由于数组也处理引用,所以不使用array1[i] = array2[i]
,使用arraycopy
或clone()
。 我认为.equals
也可以用于数组
假设我们有a
和两个不同的对象,我们想比较这两个对象的引用。 然后我们使用==
运算符,当使用a.equals(b)
,它比较字符串值。
==
检查Object引用,基本上它比较了这个hashcode。 Equals使用对象中的内容。 请记住,我们必须在我们的类中相应地覆盖.equals
方法。
==检查引用是否指向内存中的同一个对象
现在,
尽管对象类中的equals方法的代码不过是检查引用的==,但是可以重载添加自己的相等性检查。
在像String这样的类中,重写的方法检查字符串是否正确。 所以基本上它可以用来检查值是否相同。
==,它只是根据它们的地址返回一个哈希码的值,所以不同的地址,即使字符串或任何类似的数据也返回false ….这有助于满足条件,返回布尔值。