Java 具有反射的Object.equals()方法的广义重写的安全性
我已经厌倦了为我所有的类重写Object.equals,所以我提出了这个重写方法,如果在项目中的所有类中使用,它似乎会产生预期的结果Java 具有反射的Object.equals()方法的广义重写的安全性,java,reflection,overriding,Java,Reflection,Overriding,我已经厌倦了为我所有的类重写Object.equals,所以我提出了这个重写方法,如果在项目中的所有类中使用,它似乎会产生预期的结果 @Override public boolean equals(Object anObject){ if (this == anObject) { return true; } //same class? if (anObject.getClass() == this.getClass()) { Fi
@Override
public boolean equals(Object anObject){
if (this == anObject) {
return true;
}
//same class?
if (anObject.getClass() == this.getClass()) {
Field[] fields = this.getClass().getFields();
boolean fieldsEqual = true;
for (Field field : fields) {
try {
fieldsEqual &=
field.get(anObject).equals(field.get(this));
} catch (IllegalAccessException e) { }
}
//if fields equal, objects are equal.
return fieldsEqual;
}
//not the same class, so the objects aren't equal
return false;
}
这安全吗?未处理的IllegalAccessException
让我有点担心,但是考虑到该方法首先检查this
和anObject
是否是同一个类,我认为除非在运行时从类中动态删除或添加字段,否则不会发生这种情况。如果可以安全地保存一个异常,那么这可能是一个非常方便的代码片段
StackOverflow的专业人士会怎么想?我不认为尝试/捕获非法访问异常是一个好主意,这可能会导致您遇到一个非常棘手的bug进行调试,我会记录在某个地方
我通常使用for equals()。我不认为try/catch吞下IllegaAccessException是一个好主意,这可能会导致您遇到一个非常棘手的bug进行调试,我会记录在某个地方
我通常使用for equals()。我不认为try/catch吞下IllegaAccessException是一个好主意,这可能会导致您遇到一个非常棘手的bug进行调试,我会记录在某个地方
我通常使用for equals()。我不认为try/catch吞下IllegaAccessException是一个好主意,这可能会导致您遇到一个非常棘手的bug进行调试,我会记录在某个地方
我通常使用for equals()。这真是一个非常糟糕的主意 请让IDE为您生成
hashCode()
和equals()
,或者按照@Louis Wasserman的建议使用一个库,即Apache Commons Lang
除了性能差和字段为null
时抛出NullPointerException
(如注释中所述)之外,您的代码可能会运行到无限循环中:
public static class Test {
static class ClassWithUnsafeEqualsMethod {
@Override
public boolean equals(Object anObject){
if (this == anObject) {
return true;
}
//same class?
if (anObject.getClass() == this.getClass()) {
Field[] fields = this.getClass().getFields();
boolean fieldsEqual = true;
for (Field field : fields) {
try {
fieldsEqual &=
field.get(anObject).equals(field.get(this));
} catch (IllegalAccessException e) { }
}
//if fields equal, objects are equal.
return fieldsEqual;
}
//not the same class, so the objects aren't equal
return false;
}
}
static class A extends ClassWithUnsafeEqualsMethod {
B fieldB;
}
static class B extends ClassWithUnsafeEqualsMethod {
A fieldA;
}
public static void main(String... args) {
A a1 = new A();
A a2 = new A();
B b1 = new B();
B b2 = new B();
a1.fieldB = b2;
b2.fieldA = a1;
a2.fieldB = b1;
b1.fieldA = a2;
System.out.println(a1.equals(a2));
}
}
这里有一个漂亮的
java.lang.StackOverflowerError
。试试看 这真是一个非常糟糕的主意
请让IDE为您生成hashCode()
和equals()
,或者按照@Louis Wasserman的建议使用一个库,即Apache Commons Lang
除了性能差和字段为null
时抛出NullPointerException
(如注释中所述)之外,您的代码可能会运行到无限循环中:
public static class Test {
static class ClassWithUnsafeEqualsMethod {
@Override
public boolean equals(Object anObject){
if (this == anObject) {
return true;
}
//same class?
if (anObject.getClass() == this.getClass()) {
Field[] fields = this.getClass().getFields();
boolean fieldsEqual = true;
for (Field field : fields) {
try {
fieldsEqual &=
field.get(anObject).equals(field.get(this));
} catch (IllegalAccessException e) { }
}
//if fields equal, objects are equal.
return fieldsEqual;
}
//not the same class, so the objects aren't equal
return false;
}
}
static class A extends ClassWithUnsafeEqualsMethod {
B fieldB;
}
static class B extends ClassWithUnsafeEqualsMethod {
A fieldA;
}
public static void main(String... args) {
A a1 = new A();
A a2 = new A();
B b1 = new B();
B b2 = new B();
a1.fieldB = b2;
b2.fieldA = a1;
a2.fieldB = b1;
b1.fieldA = a2;
System.out.println(a1.equals(a2));
}
}
这里有一个漂亮的
java.lang.StackOverflowerError
。试试看 这真是一个非常糟糕的主意
请让IDE为您生成hashCode()
和equals()
,或者按照@Louis Wasserman的建议使用一个库,即Apache Commons Lang
除了性能差和字段为null
时抛出NullPointerException
(如注释中所述)之外,您的代码可能会运行到无限循环中:
public static class Test {
static class ClassWithUnsafeEqualsMethod {
@Override
public boolean equals(Object anObject){
if (this == anObject) {
return true;
}
//same class?
if (anObject.getClass() == this.getClass()) {
Field[] fields = this.getClass().getFields();
boolean fieldsEqual = true;
for (Field field : fields) {
try {
fieldsEqual &=
field.get(anObject).equals(field.get(this));
} catch (IllegalAccessException e) { }
}
//if fields equal, objects are equal.
return fieldsEqual;
}
//not the same class, so the objects aren't equal
return false;
}
}
static class A extends ClassWithUnsafeEqualsMethod {
B fieldB;
}
static class B extends ClassWithUnsafeEqualsMethod {
A fieldA;
}
public static void main(String... args) {
A a1 = new A();
A a2 = new A();
B b1 = new B();
B b2 = new B();
a1.fieldB = b2;
b2.fieldA = a1;
a2.fieldB = b1;
b1.fieldA = a2;
System.out.println(a1.equals(a2));
}
}
这里有一个漂亮的
java.lang.StackOverflowerError
。试试看 这真是一个非常糟糕的主意
请让IDE为您生成hashCode()
和equals()
,或者按照@Louis Wasserman的建议使用一个库,即Apache Commons Lang
除了性能差和字段为null
时抛出NullPointerException
(如注释中所述)之外,您的代码可能会运行到无限循环中:
public static class Test {
static class ClassWithUnsafeEqualsMethod {
@Override
public boolean equals(Object anObject){
if (this == anObject) {
return true;
}
//same class?
if (anObject.getClass() == this.getClass()) {
Field[] fields = this.getClass().getFields();
boolean fieldsEqual = true;
for (Field field : fields) {
try {
fieldsEqual &=
field.get(anObject).equals(field.get(this));
} catch (IllegalAccessException e) { }
}
//if fields equal, objects are equal.
return fieldsEqual;
}
//not the same class, so the objects aren't equal
return false;
}
}
static class A extends ClassWithUnsafeEqualsMethod {
B fieldB;
}
static class B extends ClassWithUnsafeEqualsMethod {
A fieldA;
}
public static void main(String... args) {
A a1 = new A();
A a2 = new A();
B b1 = new B();
B b2 = new B();
a1.fieldB = b2;
b2.fieldA = a1;
a2.fieldB = b1;
b1.fieldA = a2;
System.out.println(a1.equals(a2));
}
}
这里有一个漂亮的
java.lang.StackOverflowerError
。试试看 你需要这样做吗?比较每个值会更安全、更快。否则,只要两个对象都有相同的字段(它们在比较getClass()
之后就有相同的字段),我想您就不必担心了。看起来您重新发明了Apache的EqualsBuilder,但反射会带来巨大的运行时成本……您知道,自从Java 7以来,就有objects.equals,这将大大减少代码量。请不要懒惰,也不要为此使用反射。在海事组织,这不是一个好的解决办法。此外,大多数IDE都可以为您生成它们。毫无理由地使用反射是个坏主意。假设所有字段都是公共的是一个坏主意。在检查null
之前访问任何未知对象的属性或方法是更糟糕的主意。我想不出有哪一种情况会通过比较对象上的所有字段来检查相等性。另外,hashcode方法必须与此兼容,但是如果字段数组没有在equals和hashcode中显式排序,那么情况就不会如此。然后,无论何时访问私有字段,都会抛出非法访问——我的所有字段都是私有的。那么,对于仅通过getter存在的派生字段会发生什么?更不用说表现了。你需要这样做吗?比较每个值会更安全、更快。否则,只要两个对象都有相同的字段(它们在比较getClass()
之后就有相同的字段),我想您就不必担心了。看起来您重新发明了Apache的EqualsBuilder,但反射会带来巨大的运行时成本……您知道,自从Java 7以来,就有objects.equals,这将大大减少代码量。请不要懒惰,也不要为此使用反射。在海事组织,这不是一个好的解决办法。此外,大多数IDE都可以为您生成它们。毫无理由地使用反射是个坏主意。假设所有字段都是公共的是一个坏主意。在检查null
之前访问任何未知对象的属性或方法是更糟糕的主意。我想不出有哪一种情况会通过比较对象上的所有字段来检查相等性。另外,hashcode方法必须与此兼容,但是如果字段数组没有在equals和hashcode中显式排序,那么情况就不会如此。然后,你会得到非法的空调