基类和扩展类之间的等于不能正常工作

时间:2017-01-05 07:18:29

标签: java spring configuration java-8 equals

我正在使用Java 8和Spring。最近我有一个奇怪的(对我来说)问题。基本上,我有两个类: 1.这是一个基类:

public BaseClass {
    private int variableA;

    public BaseClass() {
        /* this is an empty costructor */ 
    }

    public BaseClass(int a) {
        this.variableA = a;
    }

    /* getter and setter method */

   @Override
   public boolean equals(Object o) {
       if (this == o) {
            return true;
       }
       if (o == null || getClass() != o.getClass()) {
           return false;
       }
       BaseClass that = (BaseClass) o;
       /* (HERE) */
       return variableA == that.variableA;
   }
}

2。一个@Configuration类,它扩展了基类:

@Configuration
@ConfigurationProperties(prefix = "config")
@RefreshScope //org.springframework.cloud.context.config
public MyClass extends BaseClass {
    private int variableB;

    /* getter and setter method */
}

我想要的只是检查两个类是否相等,只考虑baseClass中的变量。示例方法

public boolean areTheyEqual(BaseClass a, MyClass b) {
    return a.equals(b);
}

在方法areTheyEqual中,正确填写了ab类。当您查看BaseClass.equals到写(HERE)的位置时:此时我从BaseClass创建了一些MyClass。它不是NullPointer,但是variableA等于0(在MyClass中它被设置为某个值)。我不知道为什么!

如果我将方法areTheyEqual更改为:

public boolean areTheyEqual(BaseClass a, MyClass b) {
    return a.equals(new BaseClass(b));
}
一切正常。我真的很好奇为什么会这样。是否存在一些问题,使用equals我将@Configuration类MyClass转换为Object然后转换为BaseClass?

编辑1: 例如:

@Component
public class Example {
    private MyClass myClass;
    private BaseClass baseClass;

    @Autowired
    public Example(MyClass myClass) {
        this.myClass = myClass;
        this.baseClass = new BaseClass(myClass);
    }

    @Scheduled
    private void checkMe() {
        if(!areTheyEqual()) {
            /* do something */
        }
    }

    private boolean areTheyEqual() {
        /* baseClass.variableA == 2 AND myClass.variableA == 2 */
        return baseClass.equals(myClass);
    }
}

在我的问题中,equals实现是什么并不重要(btw方法是由Intellij生成的)。

我对'工作正常'的定义是: 1.当baseClass中的variableA与myClass中的variableA相同时,equals返回true 2.如果不是1.那么假

2 个答案:

答案 0 :(得分:2)

首先,当你实际上是指“对象”或“实例”时,你应该停止使用“class”这个词。您滥用该术语会使整个问题难以阅读。

然后,你得到你所要求的。在equals实现中,有声明:

if (o == null || getClass() != o.getClass()) {
    return false;
}

这意味着两个对象只能是相同的,当它们属于完全相同的类时,MyClass的实例不能等于BaseClass的直接实例,而不是MyClass的实例。

如果要同等地处理BaseClass及其子类的所有实例,无论其实际类型如何,都必须将该语句更改为

if (o == null || ! (o instanceof BaseClass)) {
    return false;
}

instanceof运算符接受指定类型的子类的实例。您无需检查this的类型,因为它暗示this instanceof BaseClass始终为true

请注意,与调用o.getClass()不同,instanceof也正确处理null,因此也可以将语句缩减为

if (! (o instanceof BaseClass)) {
    return false;
}

但这是一种编码风格决定,是使用更简单的形式还是明确的null测试。

顺便说一句,如果您的意图是所有BaseClass实例都具有相同的相等定义,无论其实际(子)类型如何,您都应该使用equals方法final ,为了清楚起见。

答案 1 :(得分:0)

由于给出的信息很少,最可能的原因似乎是您在子类中重新定义了相同的私有变量variableA,如:

public class BaseClass {
    private int variableA;

    public BaseClass (int a) {
        this.variableA = a;
    }
}

public class MyClass extends BaseClass {
    private int variableA;

    public MyClass (int a) {
        this.variableA = a;
    }
}

如果你这样做,基类'变量在子类实例中将保持为0,但只要您查看子类,您仍然会看到它正确设置了名为variableA的变量。如果你把它强制转换为超类,基类'变量将变为可见,显示0