簡體   English   中英

最終字段的初始化

[英]Initialization of final fields

有人可以向我解釋此示例的行為:

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();

    }

}

此代碼段的輸出為10 但是,當我將變量i更改為任何對象(例如Integer)時,輸出為null 但是,當我改變靜態整數輸出為10預期。

我認為,在調用任何方法(或構造函數)之前都要先初始化字段,但是這里這種方法僅適用於原始類型,而不適用於對象。

謝謝

拉迪姆

類的實例字段是在構造函數中的super()調用之后直接初始化的,無論它們是否為最終值。 但是, super()調用父級的類構造函數,該構造函數讀取因此未初始化的字段的值。

上課的時候在運行時,這意味着一類的構造函數被調用(在之前之前靜態字段initilized引用類的靜態字段都被初始化super()在類的構造函數調用)。

當字段類型為int時,為什么仍打印10的原因是,Java編譯器可以在編譯時內聯最后字段的值。 在那種情況下,程序永遠不會讀取該字段的值,因為編譯器優化了代碼,使其看起來像System.out.println(10)而不是System.out.println(i) 在這種情況下,Java編譯器不會內聯最后字段,但是,對於原始字段類型很可能這樣做,而對於大多數對象類型則不太可能。

非靜態成員:

new Child()以此順序觸發構造函數鏈接Parent()-> Child()。

當父對象被實例化時,您正在調用print(),因為它持有子對象的引用,它將調用

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

因為在這個階段,孩子的啟蒙還沒有完成。 整數i沒有任何值,因此它將輸出null

靜態變量:

一旦引用/調用了相應的類, Static data member被初始化,因此它將打印10

調用父構造函數時,子實例的實例字段未初始化

這是因為邏輯上,應該在Child存在之前Parent應該存在。

因此,首先調用Parent的構造函數,在此期間, 不會初始化Child任何字段。

因此,當您調用 Child 覆蓋print()時,將print() i的未初始化值。

靜態字段在類初始化時初始化

類加載期間發生的類初始化時進行初始化,因此它們將具有初始化的值

由於字段的最終性質,與變量不同,它在構造函數之前初始化。 因此,將打印該值。

當您聲明final Integer i = 10時會發生什么? 或者int i = 10

主代碼應為

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

然后,如果使用int或Integer,則返回10;否則,返回10。

僅使用

new Child()

則此變量沒有返回值,並且新實例被忽略。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM