Final子类构造调用父类可重写方法触发Spotbugs报错是否为预期行为?
结论
该上报属于Spotbugs的检测误报,是FindOverridableMethodCall检测器的逻辑缺陷导致的。
原因分析
MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR规则的设计初衷是规避两类风险:
- 父类构造器调用可重写方法时,子类重写该方法后会读取到子类未初始化的字段
- 非final类的构造器调用可重写方法时,该类的子类重写方法后会触发上述未初始化问题
放到当前示例代码的场景下,两类风险都不存在:
SubClass本身被final修饰,不可能存在子类,自然不存在子类重写getId方法引发的未初始化风险- 调用
getId的位置是在SubClass构造器的super(id)执行之后,父类SuperClass的初始化已经全部完成,getId依赖的id字段已经被正确赋值,不会出现读取未初始化数据的问题 - 本示例中
SubClass并没有重写getId方法,调用的完全是父类已经初始化完成的逻辑,不存在任何安全隐患。
补充说明
目前FindOverridableMethodCall检测器的实现逻辑只校验了被调用方法是否是private/final/static修饰,没有对调用方是否为final类、父类初始化是否已完成等边界场景做特殊判断,才会触发这类无意义的误报。你可以通过添加忽略注解的方式屏蔽该误报,不会影响代码的实际安全性。
内容的提问来源于stack exchange,提问作者Oboe
相关产品推荐
相关产品推荐

