java - 具有继承调用的构造函数中的最终变量

标签 java

我刚刚发现了一些很奇怪的事情。如果使用重写方法从隐式 super 构造函数调用最终变量,则该元素将永远不会在调用时初始化:

public static abstract class A {

    public A() 
    {
        doSomething();
    }

    public abstract void doSomething();

}

public static class B extends A {

    private final Object s = new Object(); 

    public B()
    {
    }

    public void doSomething() {
        System.out.println(s);
    }
}

public static void main( String[] args )
{
    new B();// prints 'null'
}

如果该方法未被重写,最终变量将被正确实例化:

public static class B  {

    private final Object s = new Object(); 

    public B()
    {
        doSomething();
    }

    public void doSomething() {
        System.out.println(s);
    }
}

public static void main( String[] args )
{
    new B(); // prints the object correctly
}

最后,对我来说更奇怪(我认为这与 String#intern 机制有关)

public static abstract class A {

    public A() 
    {
        doSomething();
    }

    public abstract void doSomething();

}

public static class B extends A {

    private final String s = "Hello"; 

    public B()
    {
    }

    public void doSomething() {
        System.out.println(s);
    }
}

public static void main( String[] args )
{
    new B(); // will print "Hello"
}

我的问题是,在第一种情况下我可以做什么来解决这个问题,我应该使用确保非空值的 getter 吗?

我有点理解为什么会发生第一种情况(构造函数在初始化任何实例变量之前隐式调用“ super ”构造函数),但是,如果我是正确的,在这种情况下为什么第三种情况会正确打印“Hello” ?

最佳答案

重要的是要理解基类的构造函数在子类的构造函数之前执行。这意味着子类的字段可能在基类构造期间尚未初始化。 (然而,它们在子类的构造过程中被初始化。)

My question is what can i do in the first case to fix this, should i use a getter that ensures non-null value ?

您发现的问题是永远不要从构造函数中调用可重写方法的原因之一。

getter 可能同样糟糕,因为 getter 也可以被重写。

而不是

Object s = new Object();

...

public void doSomething() {
    System.out.println(s);
}

B中,您可以将构造A时使用的变量作为参数传递给A的构造函数:

public B() {
    super(new Object());
}

这会传递与构造 B 对象相关的数据,以便 B 的构造函数是“自包含的”。但这相当困惑,我建议您重新考虑类的结构。


关于第三种情况:

private final String s = "Hello";

由于 "Hello" 是编译时常量表达式,并且 s 是最终的,因此 Java 编译器可以自由内联使用 s,即自行决定将 s 替换为 "Hello"

关于java - 具有继承调用的构造函数中的最终变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29347490/

相关文章:

java - Internet 上的 Java 聊天应用程序 | ConnectException(连接超时)

Java byte[] 指针转换

java - 是否可以使用JNA来获取函数的签名

java - 从显示方法打印 int[] 数组

java - 关于android中put "java"方法的问题

java - 从 Eclipse 3.2 迁移到 4.3 - 基于 RCP 的应用程序

java - 如何更正 TextField 中的希腊重音字符

java - 无法从按钮监听器接收数据

java - 如何在匿名类中为返回 void 的方法返回 String

java - java中如何退出内部循环并返回到主循环?