【问题标题】:Java: initialized inline private final field is null [duplicate]Java:初始化的内联私有最终字段为空[重复]
【发布时间】:2016-02-20 10:15:03
【问题描述】:

我无法理解为什么私有变量为空,即使它是内联初始化的。这是我的代码的 sn-p:

public abstract class A {
    public A() {
        initialize();
    }

    protected abstract void initializeLayout();
    protected void initialize() {
        // Do something
        initializeLayout();
    }
}

public abstract class B extends A {
    private final Object myVariable = new Object();

    @Override
    protected void initializeLayout() {
        // Do something with myVariable
    }
}

好吧,当这段代码到达 B.initailizeLayout 时,myVariable 为 NULL。我认为内联字段在其他所有内容之前初始化,甚至在构造函数之前。我有什么不对吗?

【问题讨论】:

  • varType 到底是什么?仅指占位符?就像任何物体一样?
  • 是的,它只是一个占位符。我应该使用更合适的东西,即使我认为它很清楚
  • 只需使用Object 作为占位符
  • Suggested reading。根据经验,从构造函数调用可覆盖的方法是 VBI(非常糟糕的主意)。

标签: java inheritance abstract


【解决方案1】:

超类A的构造函数(调用initialize()调用BinitializeLayout())在子类B的实例变量初始化之前执行。因此,您的实例变量 myVariable 那时仍为空。

【讨论】:

    【解决方案2】:

    子 B 的(可能是隐式的)构造函数将执行以下操作:

    • 将所有字段归零(null、0、0.0、false)
    • 调用超A的构造函数
      • 调用 B.initializeLayout,所有字段为空
    • 初始化在其声明中分配给的所有字段
    • 调用构造函数的其余部分

    所以你正在尝试做的事情在 java 中很容易出错。 许多样式检查器将此代码标记为不良样式(在构造函数中调用非最终方法)。

    你可以这样做

    private /*final*/ Object myVariable; // Must not be initialized!
    
    @Override
    protected void initializeLayout() {
        myVariable = new Object();
        // Do something with myVariable
    }
    

    初始化 myVariable 将在调用 initializeLayout 后初始化 myVariable。

    最好避免。

    【讨论】:

    • 很好,我喜欢你为避免这种模式而给出的推理。但是它与 calling non-final method in constructor 这句话有什么关系呢?您能否详细说明该部分或提供一些有用的链接。
    • @rajuGT 基类不能调用未在基类上声明的子类方法,因此从构造函数调用的任何方法都必须在基类上声明。任何final 基类方法都不能被子类覆盖,因此将使用基类实现(安全,因为在调用构造函数之前初始化了基类的成员)。相反,任何不是final 的方法都可能被孩子覆盖,因此会受到这种危险。因此,从构造函数调用非final 方法(不一定)是安全的。
    • @PlatinumAzure 说的。像私有方法一样调用最终(=不可覆盖)方法是安全的(如果它本身不调用任何可覆盖的)。因此,如果在构造函数中调用 setter,最好将其设为 final。
    • 谢谢两位,非常清楚的解释。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多