1.關於接口存在的繼承關係的時候是否會被初始化
首先獻上代碼
package com.example.demo.test;
public class MyTest4 {
public static void main(String[] args){
System.out.println(MyChild4.b);
}
}
interface MyParent4{
public static int a=5;
}
interface MyChild4 extends MyParent4{
public static int b=6;
}
查看執行結果
當我將Myparent4生成的class文件刪除之後,再去執行發現正常。
總結:當一個接口在初始化的時候,並不要求其父接口都完成了初始化,只有在真正使用父接口的時候(如引用接口中定義的常量時)纔會初始化。
對於一個接口來說,它的屬性就是final修飾的,對於類型來說就不是
對於接口來說,只有真正使用的時候纔會被初始化,對於類來說不管有沒有被使用,它的父類都要被初始化
2.關於類初始化的執行順序問題
package com.example.demo.test;
public class MyTest5 {
public static void main(String[] args){
Singleton singleton=Singleton.getInstance();
System.out.println(singleton.counter1);
System.out.println(singleton.counter2);
}
}
class Singleton{
public static int counter1;
public static int counter2=0;
private static Singleton singleton=new Singleton();
private Singleton(){
counter1++;
counter2++;
}
public static Singleton getInstance(){
return singleton;
}
}
執行結果就是11
但是如果調整下順序爲
package com.example.demo.test;
public class MyTest5 {
public static void main(String[] args){
Singleton singleton=Singleton.getInstance();
System.out.println(singleton.counter1);
System.out.println(singleton.counter2);
}
}
class Singleton{
public static int counter1;
private static Singleton singleton=new Singleton();
private Singleton(){
counter1++;
counter2++;
}
public static int counter2=0;
public static Singleton getInstance(){
return singleton;
}
}
它的執行結果爲1,0
總結:在加載這個類的時候都會賦予屬性一個默認的值,如果該屬性爲int類型,那麼將首先賦予默認值0,然後按照自上而下的執行順序去執行,由於counter2的定義在後面所以,首先在加載的時候已經是++了,然偶再去初始化就是設置了0,結果自然就是1,0。
3.final定義的常量,類,方法有什麼區別。
1.final定義的類,將不能被繼承
2.final定義的方法,將不能被重寫
3.final定義的屬性,將不能被重新賦值
4.類加載器
類加載器一共有兩種
1.java虛擬機自帶的加載器
根類加載器(Bootstrap)
擴展類加載器(Extension)
系統(應用類加載器)(System)
2.用戶自定義的類加載器
java.lang.ClassLoader的子類
用戶可以定製類的加載方式
5.類的加載
JVM規範允許類加載器在預料某個類將要被使用時就預先加載它,如果在預先加載的過程中遇到.class文件缺失或者存在錯誤,類加載器必須在程序首次使用該類時才報告錯誤。
如果這個類一直沒有被程序主動使用,那麼類加載器就不會報告錯誤。
類加載器在類加載之前就預先加載。
6.類的驗證
類被加載後,就進入連接階段,連接就是將已經讀入到內存的類的二進制數據合併到虛擬機的運行環境中去。
7.類的驗證
類的驗證內容:類文件的結構檢查,語義的檢查,字節碼的驗證,二進制兼容性的驗證
8.類的準備
在準備階段,JVM爲類的靜態變量分配內存,並設置默認的初始值。
9.類的初始化
在初始化階段,JVM執行類的初始化語句,爲類的靜態變量賦予初始值。
假如這個類還沒有被加載和連接,那就先進行加載和連接。
假如類存在父類,並且這個父類還沒有被初始化,那就先初始化父類。
假如類中存在初始化語句,那就一次執行這些初始化語句。
假如存在接口:
1.在初始化一個類時,並不會先初始化它所實現的接口
2.在初始化一個接口時,並不會先初始化它的父類接口
因此,一個父接口並不會因爲它的子接口或者實現類的初始化而初始化,只有當程序首次使用特定接口的靜態變量時,纔會導致接口的初始化。
10.類的初始化時機
調用ClassLoader類和loadClass方法加載一個類,並不是對類的主動使用,不會導致類的初始化。
11.雙親委派機制
一個類加載器需要加載類,那麼首先將這個請求委派給父類加載器去加載,每一層都是如此,一直遞歸到頂層也就是根類加載器去加載,當根類加載器無法完成加載的時候,就去委託它的子類去加載,也就是擴展類加載器去加載,當擴展類加載器無法完成加載的時候,再去委託它的子類系統類加載器,每一層都是如此,直到最後被加載或者加載失敗報錯爲止。