简体   繁体   English

最终字段的初始化

[英]Initialization of final fields

Can somebody explain to me behaviour of this example: 有人可以向我解释此示例的行为:

package test;

public class Test {

    static abstract class Parent{

        public Parent() {
            print();
        }
        public abstract void print();
    }

    static class Child extends Parent{

        protected final int i= 10;

        public Child() {
            super();
        }
        public void print(){
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        System.out.println("Test");
        new Child();

    }

}

Output of this snippet is 10 . 此代码段的输出为10 But when I change variable i to any object, for example Integer, output is null . 但是,当我将变量i更改为任何对象(例如Integer)时,输出为null But when I change i to static Integer output is 10 as expected. 但是,当我改变静态整数输出为10预期。

I thougth that fields are initialized before any method (or constructor) is called, but here this approach works just with primitive types and not objects. 我认为,在调用任何方法(或构造函数)之前都要先初始化字段,但是这里这种方法仅适用于原始类型,而不适用于对象。

Thanks 谢谢

Radim 拉迪姆

Instance fields of a class are initialized directly after the super() call in the constructor, whether they are final or not. 类的实例字段是在构造函数中的super()调用之后直接初始化的,无论它们是否为最终值。 However, super() invokes the parent's class constructor, which reads the value of the therefore uninitialized field. 但是, super()调用父级的类构造函数,该构造函数读取因此未初始化的字段的值。

Static fields of a class are initialized when the class is referenced at runtime, which implies that static fields are initilized before a constructor of a class gets called (before the super() call in the class's constructor). 上课的时候在运行时,这意味着一类的构造函数被调用(在之前之前静态字段initilized引用类的静态字段都被初始化super()在类的构造函数调用)。

The explanation, why 10 was still printed, when the fields type was int is, that the Java compiler may inline the value of final fields at compile time. 当字段类型为int时,为什么仍打印10的原因是,Java编译器可以在编译时内联最后字段的值。 In that case, the program never reads the value of the field since the compiler optimized the code such that it looks like System.out.println(10) instead of System.out.println(i) . 在那种情况下,程序永远不会读取该字段的值,因为编译器优化了代码,使其看起来像System.out.println(10)而不是System.out.println(i) Under which circumstances the Java compiler inlines final fields is not defined, however, it is likely to do so for primitive field types and unlikely for most Object types. 在这种情况下,Java编译器不会内联最后字段,但是,对于原始字段类型很可能这样做,而对于大多数对象类型则不太可能。

Non Static Member : 非静态成员:

new Child() triggers constructor chaining in this order Parent() --> Child(). new Child()以此顺序触发构造函数链接Parent()-> Child()。

While Parent object gets instantiated you are calling print(), as it hold reference of Child Object it will call 当父对象被实例化时,您正在调用print(),因为它持有子对象的引用,它将调用

public void print(){
            System.out.println(i); 
        }

as child initiation still not complete at this stage. 因为在这个阶段,孩子的启蒙还没有完成。 Integer i do not have any value hence it will print null . 整数i没有任何值,因此它将输出null

Static variable : 静态变量:

Static data member are initialized as soon as corresponding class has been referred/envoked hence it will print 10 . 一旦引用/调用了相应的类, Static data member被初始化,因此它将打印10

Instance Fields of child are not initialized when parent constructor is called 调用父构造函数时,子实例的实例字段未初始化

This is because of the logic that Parent should exist before the existance of Child . 这是因为逻辑上,应该在Child存在之前Parent应该存在。

So the constructor of Parent is called first and during that time none of the fields of Child are initialized. 因此,首先调用Parent的构造函数,在此期间, 不会初始化Child任何字段。

Hence when you call print() that is overridden by Child , the uninitialized value of i is printed. 因此,当您调用 Child 覆盖print()时,将print() i的未初始化值。

Static Fields are initialized at Class Initialization time 静态字段在类初始化时初始化

Are initialized at Class Initialization time which happens during class loading , so they will have the value initialized 类加载期间发生的类初始化时进行初始化,因此它们将具有初始化的值

Because of final nature of the field, it is initialized before the constructors, unlike variables. 由于字段的最终性质,与变量不同,它在构造函数之前初始化。 Therefore, the value is printed. 因此,将打印该值。

What happens when you declare final Integer i = 10 ? 当您声明final Integer i = 10时会发生什么? Or int i = 10 ? 或者int i = 10

Code for main should be 主代码应为

Child child = new Child();
child.print();

Then if you use int or Integer, it returns 10; 然后,如果使用int或Integer,则返回10;否则,返回10。

Using only 仅使用

new Child()

then there is no return value to this variable and the new instance is ignored. 则此变量没有返回值,并且新实例被忽略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM