具有反射的Object.equals()方法的广义覆盖安全性

时间:2015-01-28 17:50:55

标签: java reflection override

我已经厌倦了为我的所有类重写Object.equals,所以我提出了这个重写方法,如果在项目的所有类中使用,它会产生所需的结果。

@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让我有点担心,但鉴于该方法首先检查thisanObject是否是同一个类,我不认为除非字段是在运行时期间从类中动态删除或添加。看起来这可能是一个非常方便的代码片段,如果除了那个例外它是安全的。

StackOverflow的专业人士在想什么?

2 个答案:

答案 0 :(得分:2)

我不认为尝试/捕获吞噬IllegalAccessException是一个好主意,这可能会导致你调试一个非常毛茸茸的bug,我会记录某个地方。

我通常使用ApacheCommons equals method作为equals()。

答案 1 :(得分:1)

这真是一个非常糟糕的主意

请让IDE为您生成hashCode()equals(),或者使用库,即Apache Commons Lang EqualsBuilder,如@Louis Wasserman建议的那样。

除了性能不佳以及当字段为NullPointerException时抛出null(如评论中所述),您的代码可能会遇到无限循环:

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.StackOverflowError。试试吧!