环境
jdk:1.8+
前言
今天在跑PMD
验证代码时,报了个错误:constructors do not call overridable methods
,
具体来说就是不建议在构造方法里面去调用可以被重载的方法;
为什么呢?
这里我翻译一篇老外的文章;
示例代码
现在假设我们有如下这样的代码:
class SuperClass {
public SuperClass () {
doLogic();
}
public void doLogic() {
System.out.println("This is superclass!");
}
}
class SubClass extends SuperClass {
private String color = null;
public SubClass() {
super();
color = "Red";
}
public void doLogic() {
System.out.println("This is subclass! The color is :" + color);
// ...
}
}
public class Overridable {
public static void main(String[] args) {
SuperClass bc = new SuperClass();
// Prints "This is superclass!"
SuperClass sc = new SubClass();
// Prints "This is subclass! The color is :null"
}
}
运行后,会发现new SubClass()
打印出来的color
是null
;
分析代码,我们知道,new SuperClass()
这个调用的是父类本身的doLogic()
方法,没有问题;
当执行到new SubClass()
方法时,调用父类构造方法,但是执行doLogic()
方法时,会去调子类的;
而这时,子类的构造方法并没有执行完毕,也就是并没有执行color = "Red"
;
这也就是为什么PMD
检测代码时,不建议我们在构造方法里面调用可被重载方法的原因~~~
解决办法:在父类中,把doLogic()
方法变为不可被重载即可:
public final void doLogic() {
System.out.println("This is superclass!");
}
老外自己的解释:
The doLogic() method is invoked from the superclass’s constructor. When the superclass is constructed directly, the doLogic() method in the superclass is invoked and executes successfully. However, when the subclass initiates the superclass’s construction, the subclass’s doLogic() method is invoked instead. In this case, the value of color is still null because the subclass’s constructor has not yet concluded.
我自己的翻译:
doLogic()
方法是在超类构造函数中调用的。直接构造超类时,超类中的doLogic()
方法将被调用并成功执行。但是,当子类启动超类的构造时,将改为调用子类的doLogic()
方法。在这种情况下,由于子类的构造函数尚未结束,因此color的值仍为null。
总结
这条PMD
规则,倒是让我对final
又多了一层的理解;
翻译地址:
MET05-J. Ensure that constructors do not call overridable methods