java - 在调用父类(super class)的构造函数之前,有什么方法可以在 Java 中初始化子类的成员变量?

标签 java oop

我需要这个,因为父类(super class)中的构造函数正在调用一个在子类中被覆盖的方法。该方法返回一个值,该值传递给子类的构造函数。但是父类(super class)构造函数必须在子类构造函数之前调用,所以我没有机会保存传入的值。

最佳答案

从父类(super class)构造函数调用重写的方法根本行不通 - 不要这样做父类(super class)构造函数必须始终在子类构造函数之前完成。当父类(super class)构造函数正在执行时,所讨论的对象是父类(super class)的(半初始化)实例,而不是子类!因此,如果您尝试从构造函数调用任何重写的函数,它可能依赖的子类字段尚未初始化(正如您所观察到的)。这是类设计的基本事实,没有解决方法。

Effective Java 2nd. Ed. 中所述(第 4 章,第 17 项):

There are [...] restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

如果可以更改父类(super class)实现,请尝试将对虚函数的调用移出构造函数。实现这一目标的一种方法是使用工厂方法:

class Super {
    public void init() { ... }
}

class Subclass extends Super {
    private Subclass() { super(); ... }
    public void init() { super.init(); ... }
    public static Subclass createInstance() {
        Subclass instance = new Subclass();
        instance.init();
        return instance;
    }
}

注意 Subclass 的构造函数是私有(private)的,以确保它只能通过 createInstance() 实例化,因此实例总是被正确初始化。 OTOH 这也阻止了进一步的子类化。但是,无论如何都不推荐对具体类进行子类化——要进行子类化的类应该是抽象的(在这种情况下使用 protected 构造函数)。当然,任何进一步的子类还必须具有非公共(public)构造函数和静态工厂方法,它们会勤奋地调用 init()...

关于java - 在调用父类(super class)的构造函数之前,有什么方法可以在 Java 中初始化子类的成员变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2529612/

相关文章:

java - StringIndesOutOfBoundsException : length=0; index=2 error in Java

java - @JsonView 未传播到 ("nested")自定义序列化器

c# - 实时数据记录设计方法?

python - 如何引用对象自己的容器

php - SQL 将数据加入多维数组

java - 无法解决 HTTP 基本身份验证问题 - 消息 header 中存在非法字符(由 HMAC 编码产生)

java - 如何在三星 Galaxy S4 的相机中拍摄图像后裁剪图像

java - 为什么两个相同的字符串在 if 条件下不匹配....?

java - 多态性适用于值对象吗?

javascript - 构造函数的对象字面量返回 toString() 方法,但不返回其他方法