我有一堂课:
public class School {
private String name;
private int id;
private boolean isOpen;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
}
然后我创建了两个School实例,并比较了两个实例的相等性:
public static void main(String[] args) {
//school1
School school1 = new School();
school1.setId(1);
school1.setName("schoolOne");
//school2
School school2 = new School();
school2.setId(1);
school2.setName("schoolOne");
//result is false , why?
System.out.println("school1 == school2 ? " + school1.equals(school2));
}
即使我将相同的id
和name
设置为school1
& school2
个实例,但school1.equals(school2)
返回false,为什么?
答案 0 :(得分:5)
您必须覆盖equals(Object)
方法:
将其放在您的学校课程中:
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other == null || !(other instanceof School)) return false;
School school = (School) other;
if (school.id != this.id) return false;
if (!(school.name.equals(this.name))) return false;
if (school.isOpen != this.isOpen) return false;
if (!(school.hashCode().equals(this.hashCode()))) return false;
return true;
}
如果您要这样做,也可以覆盖hashCode()
方法。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) id;
result = prime * result + (name != null ? name.hashCode() : 0);
result = prime * result + (isOpen ? 0 : 1);
return result;
}
我相信这是覆盖hashCode()
的最佳解释。
此答案由dmeister发布,用于以下帖子:SO: Hash Code implementation。
我一直引用它,看起来在为给定类生成hashCode()
方法时,在Eclipse中使用了这个函数。
对于几乎所有情况,A提出了合理的良好实施 Josh Bloch在第8项中的“有效Java”。最好的方法就是看它 因为作者解释了为什么这种方法很好。
简短版本:
创建一个int结果并指定一个非零值。
对于在equals-Method中测试的每个字段,通过以下方式计算哈希码c:
- 如果字段f是布尔值:计算
(f ? 0 : 1)
;- 如果字段f是字节,char,short或int:计算
(int)f
;- 如果字段f为long:计算
(int)(f ^ (f >>> 32))
;- 如果字段f是浮点数:计算
Float.floatToIntBits(f)
;- 如果字段f是double:计算
Double.doubleToLongBits(f)
并像每个long值一样处理返回值;- 如果字段f是对象:使用
hashCode()
方法的结果或0
f == null
;- 如果字段f是数组:将每个字段视为单独的元素和 以递归方式计算哈希值并组合这些值 如下所述。
将哈希值c与结果合并为:
result = 37 * result + c
- 醇>
返回结果
这应该可以在大多数使用情况下正确分配哈希值。
答案 1 :(得分:2)
即使我将相同的ID和名称设置为school1& school2实例,但school1.equals(school2)返回false,为什么?
您需要在学校课程中使用equals()
方法。否则是Object类的默认方法实现。
参见默认实施
public boolean More ...equals(Object obj) {
return (this == obj);
}
在您的情况下,它是false
,因为您正在创建两个对象。有意义吗??
对于解决方案 Prefer to read。
答案 2 :(得分:2)
想象一下双胞胎(在现实生活中),即使他们有相同的外表和相同的年龄和同名,他们是否相同?不,他们不是,他们是两个不同的“实例”。
在Java中也是如此。两个不同的实例不能(隐含地)相等,因为它们各自在它们的存储器中独立存在。
但是如果你想比较它们,你可以使用equals()方法,或者你可以创建自己的新方法进行比较。
答案 3 :(得分:1)
您必须有意义地覆盖equals()
方法。从Object
类继承的默认equals()
方法检查两个引用是否在内存中引用相同的对象。
类Object的equals方法实现最具辨别力 对象可能的等价关系;也就是说,对于任何非null 引用值x和y,当且仅当x时,此方法返回true 和y引用相同的对象(x == y的值为true)。
答案 4 :(得分:1)
您已创建了2个新对象。现在您要比较2个对象引用...您没有比较字段成员值。所以比较是错误的。
对于原始数据类型,您不会遇到此问题。
答案 5 :(得分:1)
如果不覆盖public boolean equals(Object)方法,将调用Object.class中的版本:
public boolean equals(Object obj) {
return (this == obj);
}
只需比较引用(如果它们是完全相同的对象)!
因此,您必须在School.class中实现自己的equals(Object)。比较这些字段:
private String name; // use String.equals(String)
private int id; // use ==
private boolean isOpen; // use ==
答案 6 :(得分:0)
默认情况下,.equals()执行“==”即。,comapring引用。你必须覆盖equals()。
答案 7 :(得分:0)
简单的答案是,隐式超类对象的等于用于比较。
来自文档:
类Object的equals方法实现了对象上最具辨别力的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true)。 Equals method
您必须覆盖Student类中的equals和hashcode方法。
答案 8 :(得分:0)
如果不覆盖equals(),则将调用Java.lang.Object中的默认equals():
public boolean equals(Object obj) {
return (this == obj);
}
如您所见,它会比较两个对象的引用,因此在您的情况下它将返回false。
如果要比较两个对象的内容,可以:
@Override
public boolean equals(Object obj) {
// A simple impl. Pls add some checking for null/class type/.. yourself
return this.name.equals(obj.getName()) && this.id == obj.getId() && this.isOpen == isOpen();
}