java 接口初始化_Java类的初始化 | 学步园
類的初始化時機1.創建類的實例
2.訪問類或接口的靜態變量(static final常量除外,static final變量可以)3.調用類的靜態方法
4.反射(Class.forName(packageName.className))
5.初始化類的子類(子類初始化問題:滿足主動調用,即訪問子類中的靜態變量、方法,否則僅父類初始化)6.java虛擬機啟動時被標明為啟動類的類
注:加載順序:啟動類的static block最先加載(父類靜態成員、靜態代碼塊—>子類靜態成員、靜態代碼塊—>父類實例成員、代碼塊——>父類構造函數—>子類實例成員、代碼塊—>子類構造函數)
Java代碼
package?test01;
class?Singleton?{
public?static?Singleton?singleton?=?new?Singleton();
public?static?int?a;
public?static?int?b?=?0;
private?Singleton()?{
super();
a++;
b++;
}
public?static?Singleton?GetInstence()?{
return?singleton;
}
}
public?class?MyTest?{
public?static?void?main(String[]?args)?{
Singleton?mysingleton?=?Singleton.GetInstence();
System.out.println(mysingleton.a);
System.out.println(mysingleton.b);
}
}
從入口開始看
Singleton mysingleton = Singleton.GetInstence();
是根據內部類的靜態方法要一個Singleton實例。
這個時候就屬于主動調用Singleton類了。
之后內存開始加載Singleton類
1):對Singleton的所有的靜態變量分配空間,賦默認的值,所以在這個時候,singleton=null、a=0、b=0。注意b的0是默認值,并不是咱們手工為其賦予的的那個0值。
2):之后對靜態變量賦值,這個時候的賦值就是我們在程序里手工初始化的那個值了。此時singleton = new Singleton();調用了構造方法。構造方法里面a=1、b=1。之后接著順序往下執行。
3):
public?static?int?a;
public?static?int?b?=?0;
a沒有賦值,保持原狀a=1。b被賦值了,b原先的1值被覆蓋了,b=0。所以結果就是這么來的。類中的靜態塊static塊也是順序地從上到下執行的。
編譯時常量、非編譯時常量的靜態變量
Java代碼
package?test01;
class?FinalStatic?{
public?static?final?int?A?=?4?+?4;
static?{
System.out.println("如果執行了,證明類初始化了……");
}
}
public?class?MyTest03?{
public?static?void?main(String[]?args)?{
System.out.println(FinalStatic.A);
}
}
結果是只打印出了8,證明類并沒有初始化。反編譯源碼發現class里面的內容是
public static final int A = 8;
也就是說編譯器很智能的、在編譯的時候自己就能算出4+4是8,是一個固定的數字。沒有什么未知的因素在里面。
將代碼稍微改一下
public static final int A = 4 + new Random().nextInt(10);
這個時候靜態塊就執行了,證明類初始化了。在靜態final變量在編譯時不定的情況下。如果客戶程序這個時候訪問了該類的靜態變量,那就會對類進行初始化,所以盡量使用靜態final變量,盡量沒什么可變因素在里面,否則性能會有所下降。
1. ClassLoader的剖析
ClassLoader的loadClass方法加載一個類不屬于主動調用,不會導致類的初始化。如下代碼塊
Java代碼
ClassLoader?classLoader?=?ClassLoader.getSystemClassLoader();
Class?clazz?=?classLoader.loadClass("test01.ClassDemo");
并不會讓類加載器初始化test01.ClassDemo,因為這不屬于主動調用此類
jvm初始化類時,要求其父類都已經被初始化,但此規則不適用于接口1.在初始化一個類時,并不會先初始化它所實現的接口
2.在初始化一個接口時,并不會先初始化它的父類接口
因此,一個父接口并不會因為它的子接口或實現類的初始化而初始化。當且僅當程序首次使用接口的靜態變量(注意是靜態變量,使用靜態常量不會初始化)時,才回導致該接口的初始化
publicclassTest02 {publicstaticvoidmain(String[] args) {
System.out.println(J.i);
System.out.println(K.j);
}staticintout(String s,inti) {
System.out.println(s+"="+i);returni;
}
}interfaceI {inti=1;intii=Test02.out("ii",2);
}interfaceJextendsI {intj=Test02.out("j",3);intjj=Test02.out("jj",4);
}interfaceKextendsJ {intk=Test02.out("k",5);
}
調用:System.out.println(J.i);
打印:1
解釋:J.i 對于J而言沒有主動調用,對I 有調用但是i 為static final常量,因此J、I類都沒有初始化調用:System.out.println(K.j);
打印:j=3
jj=43
解釋:K.j 對于K而言沒有主動調用,對于J 調用了該接口的j為static final 變量,滿足主動調用,因此初始該接口
轉自:
http://aixiangct.blog.163.com/blog/static/91522461201131872019995?suggestedreading
總結
以上是生活随笔為你收集整理的java 接口初始化_Java类的初始化 | 学步园的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux多系统更改启动顺序
- 下一篇: 为什么很多人说 Java 不适合编写桌面