java - 父类可以创建其子类的实例吗?
问题描述
我使用 Sonarqube 对一些 Java 代码进行了单元测试,我发现的问题之一如下。
类在初始化期间不应访问自己的子类
当父类在其自己的初始化期间引用子类的成员时,结果可能不是您所期望的,因为子类可能尚未初始化。这可能会产生所谓的“初始化周期”,甚至在某些极端情况下会出现死锁。
这是 Sonarqube 用来描述问题的示例代码:
class Parent {
static int field1 = Child.method(); // Noncompliant
static int field2 = 42;
public static void main(String[] args) {
System.out.println(Parent.field1); // will display "0" instead of "42"
}
}
class Child extends Parent {
static int method() {
return Parent.field2;
}
}
接下来是引发问题的代码的简化。
abstract class Parent {
static Parent childInstance = new Child();
}
我真的不明白为什么这是一个问题。在 Sonarqube 示例中,父级field1
通过调用子级的静态方法进行初始化。这意味着我不需要在调用该方法之前实例化一个孩子。
在第二段代码中,父级试图实例化子级,而不是调用其中一个方法。
你能解释一下为什么不能在父类中引用孩子吗?
编辑:我正在使用 SonarScanner for Maven,我的 Sonarqube 版本是 8.4.1.35646。问题的规则 ID 是 S2390。
解决方案
想想这里的代码是什么时候执行的:
abstract class Parent {
static Parent childInstance = new Child();
}
由于您分配给一个static
字段,new Child()
因此必须在Parent
创建第一个实例之前很久执行。
即在类初始化期间(为了简单起见,我们假设这相当于“类加载”,即使这不太准确)。
这意味着当类Parent
被初始化时,它会创建一个新的Child
. 通常,完成初始化需要发生的第一件事是超类已经初始化。由于我们当前正在初始化Parent
,我们可以知道Child
它还不能完全初始化(根据定义,因为这需要Parent
完全初始化)。
JVM/Java 语言规范使用了一些“技巧”来实际允许此构造工作,但它们有缺点(例如能够观察未初始化的final
字段)。
可以这样想:当你忙着建造地下室时,你正试图从房子的二楼拿东西。
推荐阅读
- r - 根据其他值之间的值合并两个数据库
- c++ - C++ CRTP 初始化
- php - Wordpress 模式 json-ld 不会在搜索中显示
- ruby - 为什么创建后看不到实例变量?(属性读者)
- python - ImportError at / No module name ___ 即使满足要求
- node.js - 如何解决 Promise {
}? - html - 将 iframe 与按钮对齐
- python - Python PySpark:每周计算行数,从周一开始,到周日结束
- r - Extract common values pairs for multiple dataframes to create a new binary dataframe based on them
- javascript - 下拉列表的发布值