【发布时间】:2011-02-15 21:31:39
【问题描述】:
当我看到equals() 方法的实现时,它只做与== 相同的操作。所以我的问题是,当我们有 == 操作符时,有什么需要把它作为单独的方法来做同样的工作?
【问题讨论】:
标签: java equals referenceequals
当我看到equals() 方法的实现时,它只做与== 相同的操作。所以我的问题是,当我们有 == 操作符时,有什么需要把它作为单独的方法来做同样的工作?
【问题讨论】:
标签: java equals referenceequals
您不能重载== 运算符,但如果您希望equals(Object) 的行为与== 运算符不同,您可以覆盖== 运算符,即不比较引用而是实际比较对象(例如,使用全部或部分他们的领域)。
另外,如果您确实覆盖了equals(Object),请同时查看hashCode()。这两种方法需要兼容(即根据equals(Object)相等的两个对象需要有相同的hashCode()),否则会出现各种奇怪的错误(例如将对象添加到集合或映射时)。
【讨论】:
==比较对象references,并询问两个reference是否相同。
equals() 比较对象内容,并询问对象是否代表相同的概念。
【讨论】:
"string" == "string" 将返回 false "string".equals("string") 将返回 true
使用 o1 == o2 您比较对象 1 与 o2 是同一个对象(通过引用)
使用 o1.equals(o2),取决于对象,equals 方法会被覆盖,而不是用“return o1 == o2”之类的东西来实现
例如,您创建 2 个 Set 实例 这 2 个集合对象是 2 个不同的对象,您可以在其中任何一个对象中添加不同的元素。 set1 == set2 将始终返回 false 但是如果 set2 包含与 set1 完全相同的元素,那么 set1.equals(set2) 最终将返回 true...并且因为在 Set 类中覆盖了 equals 方法...
Set 的 Equals 实现是:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set s = (Set) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
}
【讨论】:
string1 == string2 和 string1.equals(string2)——你的答案中的两个例子都会返回 false。
这样做是为了让这成为可能:
String s1 = new String("foo");
String s2 = new String("foo");
System.out.println(s1 == s2); // false?! Different references!
System.out.println(s1.equals(s2)); // true
如果您检查String#equals() 的来源,您会发现它已经适当地覆盖了Object#equals() 以比较彼此的内部字符数组(实际 值)。许多其他类也重写了此方法。
【讨论】:
两者之间有一个非常重要的区别。
"==" 比较对象实例。默认的 equals() 实现也这样做。请运行并分析以下代码示例:
public class Person{
String name;
public Person(String name){
this.name = name;
}
//overriding equals
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( name == null ) {
if( other.name != null )
return false;
} else if( !name.equals( other.name ) )
return false;
return true;
}
}
...
...
Person john1 = new Person("John");
Person john2 = new Person("John");
System.out.println("john1 == john2:" + (john1 == john2));
System.out.println("john1.equals(john2):" + john1.equals(john2));
如您所见,"==" 将返回 false(对象是 Person 的两个不同实例),而 equals 将返回 true(因为我们定义了两个同名的 Person 相等)
【讨论】:
对于原语,== 运算符会检查两个值是否相同。
如果它不是原语,它会检查它是否是两个指针(或引用)指向一个对象的同一个实例。
equals() 方法使用== 执行自定义检查,即在Object 检查引用。但在其他类中,有时equals() 会被覆盖(我不知道这是否是正确的过去分词)。 equals() 必须检查内容。
所以,例如:
int i0 = 34;
int i1 = 34;
int i2 = 35;
// results
i0 == i1: true
i1 == i0: true
i2 == i0: false
但是如果我们有非原始人
String str0 = new String("Hello man!");
String str1 = new String("Hello man!");
String str2 = new String("!nam olleH");
String str2copy = str2;
// Results
str0 == str1: false // Pointer to two different object, so == will give false
str1 == str2: false // Idem
str2 == str2copy: true // So this are two pointers to the same object
str0.equals(str1): true // This are not the same objects, but they are equal
str1 == str1: true // Again: two times a pointer to the same object
那么,为什么str0.equals(str1) 返回true?因为 String 类具有 equals() 的覆盖。在该方法中,它不会通过执行return this == obj; 来检查它们是否相等,但在该方法中,会进行全面检查。我不知道他们使用哪种方法来比较两个字符串,但这里有两种可能的方法:
int == int)所以我希望现在清楚了。
【讨论】:
== 运算符用于比较引用。
equals() 方法是在对象定义之上定义的。
Dog d =new Dog();
Collar c =new Collar("Red");
d.setCollar(c);
Dog d2=new Dog();
Collar c2=new Collar("Red");
d2.setCollar(c2);
d2.getCollar() ==d.getCollar()
将返回 false,表示 两只狗有两个不同的项圈对象(项目)。它们不共享同一个项圈。
d2.getCollar().equals(d.getCollar())
如果衣领被定义为 [如果衣领的颜色相同,衣领相同],则返回 true 两只狗的项圈颜色相同。
class Collar{
String color="";
public Collar(String p0){
this.color=p0;
}
boolean equals(Object c){
Collar other=(Collar)c;
return this.color.equals(other.getColor());
}
public String getColor(){
return this.color;
}
}
【讨论】:
在java中,如果操作数是原始数据类型,则等于运算符(==)对两个变量的数据进行操作。但是如果操作数是对象,java 会使用引用来比较它们,因为它无法确定在对象的哪个或哪些字段上进行比较。
所以只有一种方法可以基于用户定义的字段进行比较,并且通过覆盖 equals() 方法在对象中定义,因为在 java 中不能覆盖 equals operator(==),因为 java 不支持运算符覆盖。
例如,如果您想根据名称比较 Employee,您需要通过覆盖 Employee 类中的 equals 方法来定义其逻辑,如下所示:
public class Employee {
private Integer id;
private String name;
@Override
public boolean equals(Object obj) {
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
【讨论】: