我想澄清一下我是否正确理解了这一点:
==
是参考比较,即两个对象都指向相同的存储位置.equals()
计算对象中值的比较
.equals()
视为有意义的等效对象
我想澄清一下我是否正确理解了这一点:
==
是参考比较,即两个对象都指向相同的存储位置.equals()
计算对象中值的比较.equals()
视为有意义的等效对象
Answers:
通常,您的问题的答案是“是”,但是...
.equals(...)
只会比较所写的内容进行比较,不会多也不会少。equals(Object o)
覆盖了该方法的最接近的父类的方法。Object#equals(Object o)
方法。根据对象API,这与==
; 也就是说,当且仅当两个变量都引用相同的对象且引用相同且相同时,它才返回true 。因此,您将测试对象相等性而不是功能相等性。hashCode
如果您要进行覆盖,请务必记住覆盖,equals
以免“违反合同”。根据API,如果hashCode()
两个对象的方法显示等效,则从方法返回的结果必须相同equals
。反过来并不一定是真的。==
检查内存引用,那么为什么我在[this] [1] [1]中得到这种奇怪的行为:docs.google.com/document/d/… 我希望输出为true。可以消除我的困惑
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/…)–阿比耶耶
关于String类:
equals()方法比较String实例内部(在堆上)的“值”,而不管两个对象引用是否引用相同的String实例。如果任何两个String类型的对象引用都引用同一个String实例,那就太好了!如果两个对象引用引用两个不同的String实例,则不会有任何区别。它是要比较的每个String实例内部的“值”(即:字符数组的内容)。
另一方面,“ ==” 运算符比较两个对象引用的值,以查看它们是否引用相同的String实例。如果两个对象的值引用“引用”相同的String实例,则布尔表达式的结果将为“ true” .. duh。另一方面,如果两个对象引用的值“引用” 不同的String实例(即使两个String实例都具有相同的“值”,即每个String实例的字符数组的内容相同),则布尔表达式的结果将为“ false”。
与任何解释一样,让它沉入。
我希望这可以使事情变得顺利。
String
S,==
是参考值等于为好,是的,但它通常工作(如两个String
s的相同内容将通常被==
对方),因为如何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类中的方法)的解释:
==和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
哦! 现在您看到identityHashCode(mango)等于identityHashCode(mango2),但不等于identityHashCode(mango3)
即使所有字符串变量-mango,mango2和mango3-都具有相同的值,即“ mango”,identityHashCode()
但对于所有变量而言仍然不相同。
现在尝试取消注释此行// mango2 = "mang";
,然后再次运行它,这一次您将看到所有三个identityHashCode()
都不相同。嗯,这是个有用的提示
我们知道if 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)
欢呼声:-)
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);
}
而且您将没有任何问题。
在评估代码时,很明显(==)根据内存地址进行比较,而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
*/
这是relational operator ==
和之间的区别的一般规则the method .equals()
。
object1 == object2
比较object1和object2引用的对象是否引用了Heap中的相同内存位置。
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()
I 来比较这两个对象,我需要重写人员类的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()方法
如果我们覆盖了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对象都包含相同的数据,但是引用不相同,因此等于return false和==也。但是如果我们覆盖等于方法,则
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
等于方法。
它根据对象的content(id)比较对象
但是==
仍然比较对象的引用。
==和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
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中,等于将它们视为相同,但==则不然。
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);
该字符串池(又名实习)和整数池模糊的差异进一步,并可能允许您使用==
在某些情况下为对象,而不是的.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);
基本上,==
比较两个对象在堆上是否具有相同的引用,因此,除非两个引用链接到同一对象,否则此比较将为false。
equals()
是从Object
类继承的方法。默认情况下,此方法比较两个对象是否具有相同的引用。它的意思是:
object1.equals(object2)
<=> object1 == object2
但是,如果要在同一类的两个对象之间建立相等性,则应重写此方法。hashCode()
如果您已重写,则重写方法也非常重要equals()
。
实施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"));
null
如果尚未实现,将在执行上一个代码后打印出来hashCode()
。
由于Java不支持运算符重载,因此==对于每个对象的行为都相同,但是equals()是方法,可以在Java中重写该方法,并且可以根据业务规则更改比较对象的逻辑。
Java中==和equals之间的主要区别在于,“ ==”用于比较基元,而建议使用equals()方法检查对象的相等性。
字符串比较是同时使用==和equals方法的常见方案。由于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);
}
}