本文介绍了在超级构造函数运行之前初始化字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,有没有办法在超级构造函数运行之前初始化一个字段?

In Java, is there any way to initialize a field before the super constructor runs?

即使是最糟糕的黑客我也能被编译器拒绝:

Even the ugliest hacks I can come up with are rejected by the compiler:

class Base
{
    Base(String someParameter)
    {
        System.out.println(this);
    }
}

class Derived extends Base
{
    private final int a;

    Derived(String someParameter)
    {
        super(hack(someParameter, a = getValueFromDataBase()));
    }

    private static String hack(String returnValue, int ignored)
    {
        return returnValue;
    }

    public String toString()
    {
        return "a has value " + a;
    }
}

注意:当我从继承切换到但是我仍然想知道。

Note: The issue disappeared when I switched from inheritance to delegation, but I would still like to know.

推荐答案

不,没有办法这样做。

No, there is no way to do this.

根据,在调用 super()之前,实例变量甚至不会被初始化。

According to the language specs, instance variables aren't even initialized until a super() call has been made.

这些是在类实例创建的构造器步骤中执行的步骤,取自以下链接:

These are the steps performed during the constructor step of class instance creation, taken from the link:


  1. 如果此构造函数以显式构造函数调用开始,则
    (§)将此构造函数的参数分配给此构造函数调用的新创建的参数
    变量。 8.8.7.1)的另一个构造函数在同一个类(使用这个),
    然后评估参数和处理构造函数调用
    递归使用这些相同的五个步骤。如果该构造函数
    调用突然完成,则该过程由于相同的原因突然完成
    ;

  2. 此构造函数不以显式构造函数开头
    调用同一类中的另一个构造函数(使用this)。如果
    这个构造函数是一个非Object类,那么这个
    构造函数将以显式或隐式调用
    超类构造函数(使用super)开始。使用
    递归地评估参数和
    进程的超类构造函数调用这五个步骤。如果该构造函数调用突然完成
    ,那么此过程突然完成相同的
    原因。

  3. 为此类执行实例初始化器和实例变量初始化器
    ,将实例变量
    初始化器的值分配给相应的实例变量,以
    从左到右的顺序,它们在文本中出现在类的源
    代码中。如果任何这些初始化器的执行
    导致一个异常,那么没有进一步的初始化器被处理
    ,并且该过程突然地用同样的异常完成。
    否则,继续执行步骤5.

  4. 执行此构造函数的其余部分。如果执行
    突然完成,那么这个过程突然完成
    同样的原因。否则,此过程会正常完成。

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.


这篇关于在超级构造函数运行之前初始化字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 20:40
查看更多