我理解为什么在构造函数中调用可覆盖的方法是一种不好的做法,并且可能导致错误。但是,我尝试使用前缀super来调用一个可覆盖的方法,以指定我想从超类而不是从任何其他类调用该方法。
考虑下面的例子:
public class ObjectMapperExtended extends ObjectMapper {
// fields and stuff, irrelevant to the problem
public ObjectMapperExtended () {
super();
super.registerModule(new Hibernate4Module());
}
}
在这里,我调用registerModule,这是一个来自超类的可覆盖方法。但是,我清楚地表明我想从超类中调用该方法,而不是任何其他类,但我仍然有警告声明我不应该从构造函数中调用可覆盖的方法。我从SonarQube那里得到了警告(鱿鱼:S1699,确切地说),我正在为我的代码进行静态分析。
我误解了什么吗?在这种特殊情况下指定super是否没有任何区别?
PS:使用的ObjectMapper类是来自http://fasterxml.github.io/jackson-databind/javadoc/2.3.0/com/fasterxml/jackson/databind/ObjectMapper.html
的类答案 0 :(得分:1)
你的代码是“安全的”,因为如果类超越方法,那么总是会调用super - 也许SonarQube过于谨慎。
但是,可覆盖或不覆盖,this
已经转义了构造函数 - 正在初始化的实例可以从registerModule()
传递到另一个处于不完全/不一致初始化状态的进程 - 所以无论如何都是不好的做法。即使该方法的当前实现可能不将其传递出去,未来也可能(即升级库可能会引入错误)。
要解决此问题,您可以使用//NOSONAR
标记违规行,以明确忽略(所有)警告:
public class ObjectMapperExtended extends ObjectMapper {
public ObjectMapperExtended () {
super.registerModule(new Hibernate4Module()); //NOSONAR
}
}
或(最佳实践)使用工厂方法:
public class ObjectMapperExtended extends ObjectMapper {
private ObjectMapperExtended () {}
public static ObjectMapperExtended create() {
ObjectMapperExtended obj = new ObjectMapperExtended();
obj.registerModule(new Hibernate4Module());
return obj;
}
}
顺便说一句,调用super();
是多余的;可以在不改变行为的情况下删除它。