100 java overriding equals
我试图在Java中重写equals方法.我有一个类People
,基本上有2个数据域name
和age
.现在我想覆盖equals
方法,以便我可以检查2个People对象.
我的代码如下
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
Run Code Online (Sandbox Code Playgroud)
但是当我写age.equals(other.age)
它给我错误时,equals方法只能比较String和age是Integer.
我==
建议使用运算符,我的问题解决了.
小智 119
//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 (!Person.class.isAssignableFrom(obj.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;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
跑:
- Subash Adhikari - VS - K false
- Subash Adhikari - VS - StackOverflow false
- Subash Adhikari - VS - Subash Adhikari true
- K - VS - StackOverflow错误
- K - VS - Subash Adhikari假
- StackOverflow - VS - Subash Adhikari false
- 建立成功(总时间:0秒)
Adr*_*uat 17
我不确定细节,因为你没有发布整个代码,但是:
hashCode()
,以及equals
方法应具有Object
,而不是People
其参数类型.目前你正在重载,而不是覆盖equals方法,这可能不是你想要的,特别是考虑到你稍后检查它的类型.instanceof
用来检查它是一个People对象,例如if (!(other instanceof People)) { result = false;}
equals
用于所有对象,但不用于基元.我认为你的意思是年龄是一个int
(原始的),在这种情况下只是使用==
.注意,Integer(大写'I')是一个应与equals进行比较的Object.请参阅在Java中覆盖equals和hashCode时应考虑哪些问题?更多细节.
Nev*_*rJr 10
@Override
public boolean equals(Object that){
if(this == that) return true;//if both of them points the same address in memory
if(!(that instanceof People)) return false; // if "that" is not a People or a childclass
People thatPeople = (People)that; // than we can cast it to People safely
return this.name.equals(thatPeople.name) && this.age == thatPeople.age;// if they have the same name and same age, then the 2 objects are equal unless they're pointing to different memory adresses
}
Run Code Online (Sandbox Code Playgroud)
小智 10
根据Effective Java,覆盖
equals
方法看起来很简单,但有很多方法可以解决问题,后果可能很严重.避免问题的最简单方法是不覆盖equals
方法,在这种情况下,类的每个实例只与自身相等.如果符合以下任何条件,这是正确的做法:
该类的每个实例本质上都是唯一的.对于表示活动实体而不是值的Thread这样的类也是如此.Object提供的equals实现对这些类具有完全正确的行为.
该类不需要提供"逻辑相等"测试.例如,java.util.regex.Pattern可以重写等于检查两个Pattern实例是否表示完全相同的正则表达式,但设计者并不认为客户端需要或想要此功能.在这种情况下,从Object继承的equals实现是理想的.
超类已经重写了equals,并且超类行为适用于此类.例如,大多数Set实现从AbstractSet继承它们的equals实现,从AbstractList继承List实现,从AbstractMap继承Map实现.
该类是私有的或包私有的,并且您确定它的equals方法永远不会被调用.如果您非常冒险,可以覆盖equals方法以确保不会意外调用它:
equals
方法实现了等价关系.它具有以下属性:自反:对于任何非空引用值x
,x.equals(x)
必须返回true.
对称:对于任何非空引用值x
和y
,x.equals(y)
当且仅当y.equals(x)返回true必须返回true.
传递性:对于任何非空的参考值x
,y
,z
,如果x.equals(y)
回报率true
和y.equals(z)
回报率true
,那么x.equals(z)
必须返回true
.
一致:对于任何非空引用值,x
并且y
多次调用x.equals(y)
必须始终返回true
或始终返回false
,前提是不会修改equals比较中使用的信息.
对于任何非空引用值x
,x.equals(null)
必须返回false
.
使用==
运算符检查参数是否是对此对象的引用.如果是这样,返回true.这只是一个性能优化,但如果比较可能很昂贵,那么值得做.
使用instanceof
运算符检查参数是否具有正确的类型.如果没有,则返回false.通常,正确的类型是方法发生的类.偶尔,它是由这个类实现的一些接口.如果类实现了一个优化equals协定的接口,则允许使用接口,以允许跨实现接口的类进行比较.集合接口(如Set,List,Map和Map.Entry)具有此属性.
将参数转换为正确的类型.因为此强制转换前面有一个instanceof测试,所以保证成功.
对于类中的每个"显著"现场,检查参数的那场此对象的相应字段匹配.如果所有这些测试都成功,则返回true; 否则,返回false.如果步骤2中的类型是接口,则必须通过接口方法访问参数的字段; 如果类型是一个类,您可以直接访问这些字段,具体取决于它们的可访问性.
对于类型不是float
或的原始字段double
,使用==
运算符进行比较; 对于对象引用字段,equals
递归调用该方法; 对于float
字段,使用静态Float.compare(float, float)
方法; 对于double
领域,使用Double.compare(double, double)
.浮点和双精度字段的特殊处理是由存在的作了必要的Float.NaN
,-0.0f
并且类似的双值; 虽然你可以比较float
和double
领域与静态方法Float.equals
和Double.equals
,这将需要自动装箱每个比较,这将有表现不佳.对于array
字段,请将这些准则应用于每个元素.如果数组字段中的每个元素都很重要,请使用其中一种Arrays.equals
方法.
某些对象引用字段可能合法地包含null
.为了避免a的可能性,NullPointerException
使用静态方法检查这些字段是否相等Objects.equals(Object, Object)
.
// 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
}
Run Code Online (Sandbox Code Playgroud)因为我猜的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
Run Code Online (Sandbox Code Playgroud)
在 Java 中比较对象时,您会进行语义检查,将对象的类型和识别状态与以下各项进行比较:
null
规则:
a.equals(b) == b.equals(a)
equals()
总是产生true
or false
,但从来没有 a NullpointerException
,ClassCastException
或任何其他可抛出的比较:
instanceof
用于类型比较时(只有在没有子类时才有效,并且在A extends B -> a instanceof b != b instanceof a)
.对于您的Person
班级:
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);
}
Run Code Online (Sandbox Code Playgroud)
可重用的通用实用程序类:
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)));
}
}
Run Code Online (Sandbox Code Playgroud)
对于您的Person
课程,使用此实用程序类:
public boolean equals(Object obj) {
return Equals.as(this, obj, t -> t.name, t -> t.age);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
214804 次 |
最近记录: |