java 接口初始化_Java类的初始化 | 学步园
類(lèi)的初始化時(shí)機(jī)1.創(chuàng)建類(lèi)的實(shí)例
2.訪(fǎng)問(wèn)類(lèi)或接口的靜態(tài)變量(static final常量除外,static final變量可以)3.調(diào)用類(lèi)的靜態(tài)方法
4.反射(Class.forName(packageName.className))
5.初始化類(lèi)的子類(lèi)(子類(lèi)初始化問(wèn)題:滿(mǎn)足主動(dòng)調(diào)用,即訪(fǎng)問(wèn)子類(lèi)中的靜態(tài)變量、方法,否則僅父類(lèi)初始化)6.java虛擬機(jī)啟動(dòng)時(shí)被標(biāo)明為啟動(dòng)類(lèi)的類(lèi)
注:加載順序:啟動(dòng)類(lèi)的static block最先加載(父類(lèi)靜態(tài)成員、靜態(tài)代碼塊—>子類(lèi)靜態(tài)成員、靜態(tài)代碼塊—>父類(lèi)實(shí)例成員、代碼塊——>父類(lèi)構(gòu)造函數(shù)—>子類(lèi)實(shí)例成員、代碼塊—>子類(lèi)構(gòu)造函數(shù))
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);
}
}
從入口開(kāi)始看
Singleton mysingleton = Singleton.GetInstence();
是根據(jù)內(nèi)部類(lèi)的靜態(tài)方法要一個(gè)Singleton實(shí)例。
這個(gè)時(shí)候就屬于主動(dòng)調(diào)用Singleton類(lèi)了。
之后內(nèi)存開(kāi)始加載Singleton類(lèi)
1):對(duì)Singleton的所有的靜態(tài)變量分配空間,賦默認(rèn)的值,所以在這個(gè)時(shí)候,singleton=null、a=0、b=0。注意b的0是默認(rèn)值,并不是咱們手工為其賦予的的那個(gè)0值。
2):之后對(duì)靜態(tài)變量賦值,這個(gè)時(shí)候的賦值就是我們?cè)诔绦蚶锸止こ跏蓟哪莻€(gè)值了。此時(shí)singleton = new Singleton();調(diào)用了構(gòu)造方法。構(gòu)造方法里面a=1、b=1。之后接著順序往下執(zhí)行。
3):
public?static?int?a;
public?static?int?b?=?0;
a沒(méi)有賦值,保持原狀a=1。b被賦值了,b原先的1值被覆蓋了,b=0。所以結(jié)果就是這么來(lái)的。類(lèi)中的靜態(tài)塊static塊也是順序地從上到下執(zhí)行的。
編譯時(shí)常量、非編譯時(shí)常量的靜態(tài)變量
Java代碼
package?test01;
class?FinalStatic?{
public?static?final?int?A?=?4?+?4;
static?{
System.out.println("如果執(zhí)行了,證明類(lèi)初始化了……");
}
}
public?class?MyTest03?{
public?static?void?main(String[]?args)?{
System.out.println(FinalStatic.A);
}
}
結(jié)果是只打印出了8,證明類(lèi)并沒(méi)有初始化。反編譯源碼發(fā)現(xiàn)class里面的內(nèi)容是
public static final int A = 8;
也就是說(shuō)編譯器很智能的、在編譯的時(shí)候自己就能算出4+4是8,是一個(gè)固定的數(shù)字。沒(méi)有什么未知的因素在里面。
將代碼稍微改一下
public static final int A = 4 + new Random().nextInt(10);
這個(gè)時(shí)候靜態(tài)塊就執(zhí)行了,證明類(lèi)初始化了。在靜態(tài)final變量在編譯時(shí)不定的情況下。如果客戶(hù)程序這個(gè)時(shí)候訪(fǎng)問(wèn)了該類(lèi)的靜態(tài)變量,那就會(huì)對(duì)類(lèi)進(jìn)行初始化,所以盡量使用靜態(tài)final變量,盡量沒(méi)什么可變因素在里面,否則性能會(huì)有所下降。
1. ClassLoader的剖析
ClassLoader的loadClass方法加載一個(gè)類(lèi)不屬于主動(dòng)調(diào)用,不會(huì)導(dǎo)致類(lèi)的初始化。如下代碼塊
Java代碼
ClassLoader?classLoader?=?ClassLoader.getSystemClassLoader();
Class?clazz?=?classLoader.loadClass("test01.ClassDemo");
并不會(huì)讓類(lèi)加載器初始化test01.ClassDemo,因?yàn)檫@不屬于主動(dòng)調(diào)用此類(lèi)
jvm初始化類(lèi)時(shí),要求其父類(lèi)都已經(jīng)被初始化,但此規(guī)則不適用于接口1.在初始化一個(gè)類(lèi)時(shí),并不會(huì)先初始化它所實(shí)現(xiàn)的接口
2.在初始化一個(gè)接口時(shí),并不會(huì)先初始化它的父類(lèi)接口
因此,一個(gè)父接口并不會(huì)因?yàn)樗淖咏涌诨驅(qū)崿F(xiàn)類(lèi)的初始化而初始化。當(dāng)且僅當(dāng)程序首次使用接口的靜態(tài)變量(注意是靜態(tài)變量,使用靜態(tài)常量不會(huì)初始化)時(shí),才回導(dǎo)致該接口的初始化
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);
}
調(diào)用:System.out.println(J.i);
打印:1
解釋:J.i 對(duì)于J而言沒(méi)有主動(dòng)調(diào)用,對(duì)I 有調(diào)用但是i 為static final常量,因此J、I類(lèi)都沒(méi)有初始化調(diào)用:System.out.println(K.j);
打印:j=3
jj=43
解釋:K.j 對(duì)于K而言沒(méi)有主動(dòng)調(diào)用,對(duì)于J 調(diào)用了該接口的j為static final 變量,滿(mǎn)足主動(dòng)調(diào)用,因此初始該接口
轉(zhuǎn)自:
http://aixiangct.blog.163.com/blog/static/91522461201131872019995?suggestedreading
總結(jié)
以上是生活随笔為你收集整理的java 接口初始化_Java类的初始化 | 学步园的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux多系统更改启动顺序
- 下一篇: android 服务的应用,在Activ