天天看點

反射機制

反射機制

反射機制最重要的部分是準許你檢查類的結構。java.lang.reflect包中的三個類Field、Method、Constructor相應的描述了一個類的字段、方法、構造函數。使用這些類的時候必須要遵循下面步驟:

第一步是獲得你想操作的類的java.lang.Class對象。下面就是獲得一個Class對象的方法之一:Classc=Class.forName("java.lang.String");//這條語句得到一個String類的類對象。還有另一種方法:Classc=int.class;或者Classc=Integer.TYPE;//可獲得基本類型的類資訊。

第二步是調用諸如getDeclaredMethods的方法,以取得該類中定義的所有方法的清單。

Methodm[]=c.getDeclaredMethods();

System.out.println(m[0].toString());//以文本方式列印出String中定義的第一個方法的原型。

Class.forName的作用?為什麼要用?

答:Class是運作中的class類,forName(className)是将這個名為className的類裝入JVM,這樣就可以動态的加載類,通過Class的反射機制可以獲得此類的一些資訊。Class.forName的作用動态加載和建立Class對象。

類加載器是用來加載.class檔案,讀取.class檔案的位元組碼并加載到記憶體中。

關于類的初始化(執行static程式段):

1、Aa=newA();//在類加載的時候即進行初始化

2、Class.forName(A);//在類加載(載入class)的時候即進行初始化

3、Class.forName(A,false,classLoader);//在newInstance的時候進行初始化

4、classLoader.loadClass(A);//在newInstance的時候進行初始化

static塊僅執行一次

(1)使用Class.forName()

+-publicstaticClassforName(StringclassName)

+-publicstaticClassforName(StringclassName,booleaninitialize,ClassLoaderloader)

參數說明:

className-所需類的完全限定名(包括全路徑)

initialize-是否必須初始化類(靜态代碼塊的初始化)

loader-用于加載類的類加載器

不管使用的是new來執行個體化某個類、或是使用隻有一個參數的Class.forName()方法,内部都隐含了“載入類+運作靜态代碼塊”的步驟。而使用具有三個參數的Class.forName()方法時,如果第二個參數為false,那麼類加載器隻會加載類,而不會初始化靜态代碼塊,隻有當執行個體化這個類的時候,靜态代碼塊才會被初始化,靜态代碼塊是在類第一次執行個體化的時候才初始化的。

Class類和對象

類是程式的一部分,每個類都有一個Class對象。換言之,每次寫一個新類時,同時也會建立一個Class對象(更恰當地說,是儲存在一個完全同名的.class檔案中)。在運作期,一旦我們想生成這個類的對象,運作這個程式的Java虛拟機(JVM)首先就會檢查這個類的Class對象是否已經載入。若尚未載入,JVM就會根據類名查找.class檔案,并将其載入。是以Java程式并不是一開始就被完全加載的,這一點與許多傳統語言都不同。

一旦某個類的Class對象被載入記憶體,它就被用來建立這個類的所有對象。注意:Class對象僅在需要的時候才被加載。Class類沒有公共構造方法。Class對象是在加載類時由Java虛拟機以及通過調用類加載器中的defineClass方法自動構造的,是以不能顯式地聲明一個Class對象。

基本的Java類型(boolean、byte、char、short、int、long、float和double)和關鍵字void也都對應一個Class對象。每個數組屬于被映射為Class對象的一個類,所有具有相同元素類型和維數的數組都共享該Class對象。

有三種方法可以擷取Class的對象:

1、調用Object類的getClass()方法來得到Class對象。例如:

MyObjectx;Classc1=x.getClass();

2、使用Class類的中靜态forName()方法獲得與字元串對應的Class對象。例如:

Classc2=Class.forName("MyObject");//MyObject必須是接口或者類的名字。

3、如果T是一個Java類型,那麼T.class就代表了比對的類對象。例如

Classcl1=Manager.class;Classcl2=int.class;Classcl3=Double[].class;

注意:Class對象實際上描述的隻是類型,而這類型未必是類或者接口。例如上面的int.class是一個Class類型的對象。

二、Class類的常用方法

1、getName()以String的形式傳回此Class對象所表示的實體(類、接口、數組類、基本類型或void)名稱。

2、newInstance()為類建立一個執行個體。例如:x.getClass.newInstance()。newInstance()方法調用預設構造器(無參數構造器)初始化建立對象。

3、getClassLoader()傳回該類的類加載器。

4、getSuperclass()傳回表示此Class所表示的實體的超類的Class。

5、isArray()判定此Class對象是否表示一個數組類。

三、Class的一些使用技巧

1、forName和newInstance結合起來使用,可以根據存儲在字元串中的類名建立對象。例如Objectobj=Class.forName(s).newInstance();

2、虛拟機為每種類型管理一個獨一無二的Class對象。是以可以使用==操作符來比較類對象。例如:if(e.getClass()==Employee.class)...

javaclassLoader原理

JavaClassLoader是一個重要的Java運作時系統元件。它負責在運作時查找和裝入類檔案的類。類裝載器是用來把類(class)裝載進JVM的。JVM規範定義了兩種類型的類裝載器:啟動内裝載器(bootstrap)和使用者自定義裝載器。

bootstrap是JVM自帶的類裝載器,用來裝載核心類庫,如java.lang.*。java.lang.Object是由bootstrap裝載的。Java提供了抽象類ClassLoader,所有使用者自定義類裝載器都執行個體化自ClassLoader的子類。

SystemClassLoader是一個特殊的使用者自定義類裝載器,由JVM的實作者提供,在程式設計者不特别指定裝載器的情況下預設裝載使用者類。系統類裝載器可以通過ClassLoader.getSystemClassLoader()方法得到。

類裝載器把一個類裝入Java虛拟機中,要經過三個步驟:裝載、連結和初始化,其中連結又可以分成校驗、準備和解析三步,除了解析外,其它步驟是嚴格按照順序完成的,各個步驟的主要工作如下:

  (1)裝載:尋找一個類或是一個接口的二進制形式并用該二進制形式來構造代表這個類或是這個接口的class對象的過程。

(2)連結:就是把class類型資料合并到JVM得運作時狀态中去。執行校驗、準備和解析步驟;

校驗:檢查導入類或接口的二進制資料的正确性;準備:給類的靜态變量配置設定并初始化存儲空間;解析:将符号引用轉成直接引用;

(3)初始化:初始化Java代碼和靜态Java代碼塊。初始化在JVM第一次主動使用該類型時進行的。所謂主動使用包括以下幾種情況:

[1]建立類的新執行個體時(new指令或通過不明确的建立,反射,克隆或反序列化)

[2]調用類的靜态方法時

[3]使用類的靜态字段,或對該字段指派時(final修飾的靜态字段除外)

[4]初始化某個類的子類時

[5]JVM啟動時某個被标明為啟動類的類即含有main()方法的類

數組類的Class對象不是由類裝載器建立的,而是由Java運作時根據需要自動建立。數組類的類裝載器由Class.getClassLoader()傳回,該裝載器與其元素類型的類裝載器是相同的;如果該元素類型是基本類型,則該數組類沒有類裝載器。

虛拟機加載類的途徑:

1、Dogdog=newDog();

2、Classclazz=Class.forName(“Dog”);

Objectdog=clazz.newInstance();

3、Classclazz=classLoader.loadClass(“Dog”);

那麼,1和2和3究竟有什麼差別呢?分别用于什麼情況呢?

1和2使用的類加載器是相同的,都是目前類加載器。(即:this.getClass.getClassLoader)。

3由使用者指定類加載器。如果需要在目前類路徑以外尋找類,則隻能采用第3種方式。第3種方式加載的類與目前類分屬不同的命名空間。

另外,第1種和第2種都會導緻執行類的靜态初始化語句,而第3種情況不會。另外第1種抛出Error,第2、3種抛出Exception,它們分屬于不同的異常/錯誤分支。

上一篇: 反射機制
下一篇: 反射機制

繼續閱讀