[Java] 類和接口的初始化步驟 - 繼承方面


類和接口在初始化化時,處理繼承層級的方法不一樣。

類繼承的初始化:通過引用 static 字段,觸發某個類的初始化,則聲明該字段的類,以及該類的父類被初始化。

接口繼承的初始化:通過引用 static 字段,觸發某個接口的初始化,則聲明該字段的接口會被初始化,但該接口的父接口不會被初始化。

想了解其他觸發類初始化的方法,可參看另一篇博文 類的初始化步驟 。

 

注意一點,接口字段全部隱式地被修飾為 public, static, final 。因此,所有的接口字段實際上都是 static 的,無論有沒有顯示地聲明 static 。這點和接口無法被實例化規定是相吻合的。

類繼承的初始化例子

Super, 父類。

C, 繼承 Super 類。

Sub, 繼承 C 類。

InitDemo, 演示類繼承的初始化。

package execution.initializationExtends;
public class Super {
static String superName = "superName"; static{ System.out.println(" initializing Super "); } }

 

package execution.initializationExtends;
public class C extends Super{
    
    static String cName = "cName";
    static {
        System.out.println(" initializing C ");
    }
}

 

package execution.initializationExtends;
public class Sub extends C{

    static{
        System.out.println(" initializing Sub ");
    }
}

InitDemo 演示類繼承的初始化,通過引用類的變量,觸發類被初始化。需要注意的是,在這里 cName 字段的聲明類是 C 類,不是 Sub 類。

package execution.initializationExtends; 
public class InitDemo {
    public static void main(){
        System.out.println(Sub.cName);
    }
}

輸出

 initializing Super 
 initializing C 
cName

根據初始化可見,只有 static 字段的聲明類 C ,以及其父類 Super 被初始化了,輸出代碼中 Sub 類沒有被初始化。

 

接口繼承的初始化例子

Output,用於輸出接口初始化的情況。由於接口內不能直接帶靜態代碼塊,所有通過 Output 類輸出接口的初始化情況。

SuperI, 接口父類;

I, 繼承 SuperI 接口;

SubI, 繼承 I 接口。

InitIDemo,演示接口繼承的初始化。

package execution.initializationExtendsI;
public class Output {
    
    public static String printWhenInit(String s){
        System.out.println(s);
        return s.substring(s.indexOf(" "));
    }
}

 

package execution.initializationExtendsI;
public interface SuperI {
    public static String superField = Output.printWhenInit(" initializing SuperI.superField ");
}

 

package execution.initializationExtendsI;
public interface I extends SuperI{
    public static String iField = Output.printWhenInit("initializing I.iField ");
}

 

package execution.initializationExtendsI;
public interface SubI extends I {
    public static String subField = Output.printWhenInit(" initializing SubI.subField ");
}

和前面的類繼承初始化例子相似,iField 字段的聲明接口不是 SubI, 而是 I 。

package execution.initializationExtendsI;
public class InitIDemo {
    public static void main(){
        System.out.println(SubI.iField);
    }
}

 

輸出

initializing I.iField 
 I.iField 

由輸出可見,只有 iField 字段的聲明接口 I 被初始化了。輸出代碼的 SubI 、父接口 SuperI 都沒有被初始化。

 

參考資料

9.3 Field (Constant) Declarations, The Java Language Specification, Java SE 8 Edition

12.4.1 When Initialization Occurs, The Java Language Specification, Java SE 8 Edition

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM