如何在Java中重写equals方法
我试图重写Java中的equals方法。我有一个类如何在Java中重写equals方法,java,overriding,equals,Java,Overriding,Equals,我试图重写Java中的equals方法。我有一个类People,它基本上有两个数据字段name和age。现在我想重写equals方法,这样我就可以在两个人对象之间进行检查 我的代码如下 public boolean equals(People other){ boolean result; if((other == null) || (getClass() != other.getClass())){ result = false; } // end if
People
,它基本上有两个数据字段name
和age
。现在我想重写equals
方法,这样我就可以在两个人对象之间进行检查
我的代码如下
public boolean equals(People other){
boolean result;
if((other == null) || (getClass() != other.getClass())){
result = false;
} // end if
else{
People otherPeople = (People)other;
result = name.equals(other.name) && age.equals(other.age);
} // end else
return result;
} // end equals
但当我写
age.equals(other.age)
时,它会给我错误,因为equals方法只能比较字符串,而age是整数
解决方案
我按照建议使用了
==
运算符,我的问题就解决了。因为我猜年龄
属于int
类型:
public boolean equals(Object other){
boolean result;
if((other == null) || (getClass() != other.getClass())){
result = false;
} // end if
else{
People otherPeople = (People)other;
result = name.equals(otherPeople.name) && age == otherPeople.age;
} // end else
return result;
} // end equals
我不确定细节,因为您尚未发布全部代码,但是:
- 记住也要覆盖
hashCode()
方法的参数类型应该是equals
,而不是Object
。目前,您正在重载而不是重写equals方法,这可能不是您想要的,特别是考虑到您稍后会检查它的类型People
- 您可以使用
检查它是否为人员对象,例如instanceof
如果(!(其他人员实例)){result=false;}
用于所有对象,但不用于基本体。我想你的意思是年龄是一个equals
(原语),在这种情况下只需使用int
。请注意,整数(大写“I”)是一个对象,应该与equals进行比较=
有关详细信息,请参阅。如果年龄为int,则应使用==如果它是Integer对象,则可以使用equals()。
如果重写equals,还需要实现hashcode方法。合同的详细信息可以在对象的javadoc中找到,也可以在web的各个页面上找到。引入一个新的方法签名来更改参数类型,称为重载:
公共布尔等于(其他人){
这里的人
与对象
不同
// Class with a typical equals method
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
this.areaCode = rangeCheck(areaCode, 999, "area code");
this.prefix = rangeCheck(prefix, 999, "prefix");
this.lineNum = rangeCheck(lineNum, 9999, "line num");
}
private static short rangeCheck(int val, int max, String arg) {
if (val < 0 || val > max)
throw new IllegalArgumentException(arg + ": " + val);
return (short) val;
}
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber)o;
return pn.lineNum == lineNum && pn.prefix == prefix
&& pn.areaCode == areaCode;
}
... // Remainder omitted
}
当一个方法签名与其超类的签名保持一致时,它被称为重写,而@Override
注释有助于在编译时区分这两种签名:
@覆盖
公共布尔等于(对象其他){
如果看不到年龄的实际声明,就很难说出现错误的原因。//作者K@stackoverflow
//Written by K@stackoverflow
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("Subash Adhikari", 28));
people.add(new Person("K", 28));
people.add(new Person("StackOverflow", 4));
people.add(new Person("Subash Adhikari", 28));
for (int i = 0; i < people.size() - 1; i++) {
for (int y = i + 1; y <= people.size() - 1; y++) {
boolean check = people.get(i).equals(people.get(y));
System.out.println("-- " + people.get(i).getName() + " - VS - " + people.get(y).getName());
System.out.println(check);
}
}
}
}
//written by K@stackoverflow
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
final Person other = (Person) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if (this.age != other.age) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 53 * hash + this.age;
return hash;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
公共班机{
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
//此处的TODO代码应用程序逻辑
ArrayList people=新建ArrayList();
添加(新人物(“Subash Adhikari”,28));
添加(新人员(“K”,28));
添加(新人员(“StackOverflow”,4));
添加(新人物(“Subash Adhikari”,28));
对于(inti=0;i 对于(int y=i+1;y在Java中比较对象时,进行语义检查,将对象的类型和标识状态与以下对象进行比较:
- 自身(同一实例)
- 自身(克隆或重建副本)
- 其他不同类型的对象
- 相同类型的其他对象
null
规则:
- 对称性:
a.equals(b)==b.equals(a)
equals()
始终产生true
或false
,但决不会产生NullpointerException
、ClassCastException
或任何其他可丢弃的异常
比较:
- 类型检查:两个实例都必须是相同的类型,这意味着您必须比较实际的类是否相等。当开发人员使用
instanceof
进行类型比较时,这通常无法正确实现(它只在没有子类的情况下工作,并且在A扩展B->A instanceof B!=B instanceof A时违反对称规则)
- 识别状态的语义检查:确保您了解实例的识别状态。可以通过其社会保险号识别人员,但不能通过头发颜色(可染色)、姓名(可更改)或年龄(随时更改)进行识别。只有通过值对象才能比较完整状态(所有非瞬态字段),否则仅检查标识实例的内容
对于您的人员
班级:
public boolean equals(Object obj) {
// same instance
if (obj == this) {
return true;
}
// null
if (obj == null) {
return false;
}
// type
if (!getClass().equals(obj.getClass())) {
return false;
}
// cast and compare state
Person other = (Person) obj;
return Objects.equals(name, other.name) && Objects.equals(age, other.age);
}
可重用的通用实用程序类:
public final class Equals {
private Equals() {
// private constructor, no instances allowed
}
/**
* Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state
*
* @param instance object instance (where the equals() is implemented)
* @param other other instance to compare to
* @param stateAccessors stateAccessors for state to compare, optional
* @param <T> instance type
* @return true when equals, false otherwise
*/
public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) {
if (instance == null) {
return other == null;
}
if (instance == other) {
return true;
}
if (other == null) {
return false;
}
if (!instance.getClass().equals(other.getClass())) {
return false;
}
if (stateAccessors == null) {
return true;
}
return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other)));
}
}
public boolean equals(Object obj) {
return Equals.as(this, obj, t -> t.name, t -> t.age);
}
第10项:当压倒一切时,遵守总合同
,重写equals
方法似乎很简单,但有很多方法会出错,并且后果可能很严重。避免问题的最简单方法不是重写equals
方法,在这种情况下,类的每个实例都只与自身相等。如果出现以下任何一种情况,那么这样做是正确的:pply:
- 类的每个实例本身都是唯一的。对于表示活动实体而不是值的类(如线程),这一点是正确的。对象提供的equals实现对这些类具有完全正确的行为
- 类不需要提供“逻辑等式”test.例如,java.util.regex.Pattern可以重写equals以检查两个模式实例是否表示完全相同的正则表达式,但设计者认为客户端不需要或不需要此功能。在这种情况下,从对象继承的equals实现是理想的
- 一个超类已经重写了equals,并且超类行为适合于该类。例如,大多数集合实现从AbstractSet继承equals实现,从AbstractList继承List实现,从AbstractMap继承Map实现
- 该类是私有的或包私有的,您可以确定它的equals方法永远不会被调用
// Class with a typical equals method
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
this.areaCode = rangeCheck(areaCode, 999, "area code");
this.prefix = rangeCheck(prefix, 999, "prefix");
this.lineNum = rangeCheck(lineNum, 9999, "line num");
}
private static short rangeCheck(int val, int max, String arg) {
if (val < 0 || val > max)
throw new IllegalArgumentException(arg + ": " + val);
return (short) val;
}
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber)o;
return pn.lineNum == lineNum && pn.prefix == prefix
&& pn.areaCode == areaCode;
}
... // Remainder omitted
}
public class Test {
public String a;
public long b;
public Date c;
public String d;
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Test)) {
return false;
}
Test testOther = (Test) obj;
return (a != null ? a.equals(testOther.a) : testOther.a == null)
&& (b == testOther.b)
&& (c != null ? c.equals(testOther.c) : testOther.c == null)
&& (d != null ? d.equals(testOther.d) : testOther.d == null);
}
}