Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的内联初始化块_Java_Initialization - Fatal编程技术网

java中的内联初始化块

java中的内联初始化块,java,initialization,Java,Initialization,我有一节课 public class MyMain{ public static void main(String... arg){ Temp t = new Temp(){ { System.out.println(" instance initialize"); } }; } } class Temp{

我有一节课

public class MyMain{
    public static void main(String... arg){
            Temp t = new Temp(){
                {
                    System.out.println(" instance initialize");
                }
            };

        }
    }

class Temp{
    int i;

    {
        i=9;
        System.out.println("Static"+i);
    }
    Temp(){
        System.out.println("Temp const "+i);
    }
}
当我执行main方法时,输出如下:

Static9
Temp const 9
instance initialize

理想情况下,块在构造函数之前执行,但内联初始化块在构造函数之后调用。为什么?

必须先将对象放入内存,然后才能对其执行任何其他操作。对象在内存中构造,然后您的控制台打印。

您正在创建
Temp
的子类。对于每个类,任何实例初始值设定项都会在构造函数体之前执行,但超类会在子类初始化之前进行初始化。因此,执行流程是:

  • 对象中的初始值设定项
  • 对象中的构造函数主体
  • Temp
  • 构造函数主体位于
    Temp
  • 匿名类中的初始值设定项
  • 匿名类中的构造函数主体(无)

我强烈建议您重构任何看起来像这样的代码-目的是清晰而不是聪明。

内联初始化块在您当前实例化的匿名类的基类的构造函数之后调用,在匿名类的空隐式构造函数之前调用本身。

说明了施工过程中发生的事情的顺序(重点是我的):

就在对新创建的对象的引用作为 结果,将处理指示的构造函数以初始化新的 对象,请使用以下过程:

(3) 此构造函数不会以同一类中另一个构造函数的显式构造函数调用开始(使用此函数)。如果 此构造函数用于对象以外的类,则 构造函数将以显式或隐式调用 超类构造函数(使用super)评估参数和 使用这些函数递归调用超类构造函数的过程 相同的五个步骤。如果构造函数调用突然完成, 然后,出于同样的原因,此过程突然完成。否则,, 继续执行步骤4

(4) 为此类执行实例初始值设定项和实例变量初始值设定项,分配实例变量的值 在 它们在源代码中从左到右的文本显示顺序 为了班级。如果执行这些初始值设定项中的任何一个会导致 异常,则不再处理其他初始值设定项,并且 过程突然完成,但出现了相同的异常。否则,, 继续执行步骤5

(5) 执行此构造函数主体的其余部分。如果该执行突然完成,则此过程将针对 同样的原因。否则,此过程将正常完成


总之,超类构造函数(步骤3)在实例初始化器(步骤4)之前执行。这两个类都是在“此构造函数主体的其余部分”(您的示例中没有)之前执行的。

您实际创建的不是
Temp
类实例,而是继承自
Temp
的某个类的实例


因此,首先调用
Temp
初始值设定项(
Temp
中的一个匿名块及其构造函数),然后调用一个匿名类中的初始值设定项。

第1点:要清楚,您有两个实例初始值设定项:一个在Temp类中,另一个在main()中创建的匿名内部类中方法,该方法是Temp的子类

第2点:实例初始值设定项实际上不是在构造函数之前运行的,在委托给超级构造函数之后,在初始化实例字段并完成构造函数之前

第3点:在代码中,每个初始值设定项都在适当的时间正确执行。我认为您期望第二个类与第一个类同时执行,但这是不正确的,因为正如第1点所指出的,它们是两个不同类的初始值设定项

第4点:您可能还混淆了静态和静态。它们是两个截然不同的东西。

在您的代码中

Temp t = new Temp(){
    {
        System.out.println(" instance initialize");
    }
};
您正在创建扩展临时类的匿名类的对象

正在创建子类的对象:

initialize block from Superclass
constructor of Superclass
initialize block from Subclass
constructor of Subclass

作为一个侧面点,这不是静态的,你打印静态的。这和C#中的行为一样吗?@Gab:不,不完全一样。在C#中,派生类中的变量初始值设定项在基类中的构造函数之前执行。