91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java開發中類的加載及反射機制是什么

發布時間:2021-07-12 14:17:27 來源:億速云 閱讀:120 作者:chen 欄目:編程語言

本篇內容介紹了“Java開發中類的加載及反射機制是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

JAVA中類文件加載是動態的。JVM指令是被封裝在了.class文件里面,而.class文件的加載過程是動態的,也就是說當我們用到的時候才會去加載,如果不用的話,就不會去加載我們的類。這里所說的用到包括兩種方式,***種就是new一個對象的時候(這個時候要特別注意,當設計到多態的時候,就會有一點點變化,這時候編譯器會做一些優化,這樣以來當加載的時候會提前加載設計到多態的類,關于這一點下面有個例子(example 1)來說明。另一種就是當一個類的靜態代碼被調用的時候。

java 代碼
//example 1
//Zoo.java
abstract class Animal {
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
private Animal am; //Example 1.1
//private Dog am; Example 1.2
private Tiger tiger;
Zoo(){
tiger = new Tiger();
am = new Dog();
}
public static void main(String [] args){
System.out.println("new Zoo before");
Zoo z = new Zoo();
System.out.println("new Zoo after ");
}
}

我們可以看出:當我們將子類對象賦值給父類時,編譯器會做一點優化,于是加載器在還沒有new子類對象的時候已經加載了父類以及子類(example1.1結果),當不存在多態的時候,我們可以看到是當要new Dog()的時候才會加載Dog以及父類。無論何種方式,在new之前,類確實已經加載到了內存中。

JAVA為我們提供了兩種動態機制。***種是隱式機制。其實new一個對象和調用類的靜態方法時,就是隱式機制在工作。第二種是顯示機制。顯示的機制又有兩種策略(***種是用java.lang.Class的forName(String str)方法,第二種是用java.lang.ClassLoader的loadClass())。

***種:利用forName方法

當我們查API文檔就會發現forName方法有兩種形式。分別如下:

public static Class<?> forName(String className)
throws ClassNotFoundException
public static Class<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException

先來說說第二種方法:第二個方法值得注意的就是第二個參數boolean initialize,如果我們把這個參數設置為false,那么當我們加載完類后就不會執行靜態代碼和靜態的初始化動作。只有當我們new一個對象的時候才會初始化。而第三個參數是用來指明類的加載器的。

如果查看java.lang.Class類的源代碼,上述兩種方法最終都會調用Class類中的私有的native方法forName0(),此方法的聲明如下:

private static native Class forName0(String name, boolean init,ClassLoader loader)
throws ClassNotFoundException;

所以當我們調用Class.forName(name )時,其實是在方法內部調用了:

forName0(name, true, ClassLoader.getCallerClassLoader());

當我們調用Class.forName(name, initialize, loader )的時候,實際上此方法內部調用了:

forName0(name, initialize, loader);

下面看一個例子,如果方法中第二個參數為false的情況:

java 代碼
//example 2.1
//Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
public static void main(String [] args)throws Exception {
System.out.println("new Zoo before");
Zoo z = new Zoo();
Class c = Class.forName("Dog",false,z.getClass().getClassLoader());
System.out.println("initilize before ");
Animal dog = (Animal)c.newInstance();
System.out.println("new Zoo after ");
}
}

類加載完成后并沒有立即執行靜態初始化代碼,而是到了實例化的時候才進行了靜態初始化。有時候我們會說靜態代碼是在類***次被加載時執行的,并且只執行一次。其實這是對與new一個對象,***次訪問類的靜態代碼以及第二個參數為true時而言的,對于動態的加載來說,如果forName方法的第二個參數設置為false,那么就是在實例化的時候才會執行靜態初始化。當然默認情況下第二個參數是true。

第二種方法:利用Class對象獲取的ClassLoader裝載

下面是一個簡單的例子:

java 代碼
//Example 2.2
//Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
public static void main(String [] args)throws Exception {
Class c = Zoo.class;
ClassLoader loader = c.getClassLoader();
System.out.println("loader before");
Class dog = loader.loadClass("Dog");
System.out.println("instance before ");
Animal an = (Animal)dog.newInstance();
}
}

loader完成以后并沒有立即進行靜態代碼的執行。只有當newInstance()的時候才執行靜態初始化,這和把public static Class forName(String name, boolean initialize, ClassLoader loader)的第二個參數指定為false的情況完全一樣。其實每當我們寫完一個編譯單元以后就會得到一個.calss文件,這個文件中就包含了該類的Class對象。JVM就是利用這個class對象來進行動態裝載類的。

“Java開發中類的加載及反射機制是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

龙井市| 离岛区| 东港市| 北川| 青神县| 合作市| 星座| 海南省| 宜章县| 同江市| 江都市| 张家口市| 南昌市| 泾源县| 枣阳市| 土默特左旗| 诏安县| 南木林县| 凤台县| 常德市| 六安市| 綦江县| 峨边| 南投县| 陈巴尔虎旗| 松滋市| 南部县| 留坝县| 赫章县| 宾川县| 丹巴县| 石棉县| 凤山县| 海淀区| 广宗县| 时尚| 靖边县| 甘洛县| 文成县| 赞皇县| 钟山县|