標籤:
上一篇部落格中我們提到了ClassLoader,知道ClassLoader是用來動態載入某個Class檔案到記憶體當中,但是這個Class檔案是怎麼產生的呢?從何而來?這又涉及到另一個概念—java.lang.Class。
Class 是java的一個特殊類,對於我們定義的類、介面,它更算是一個抽象類別。Class類用於封裝被裝入到JVM中的類(包括類和介面)的資訊。 當一個類和介面被裝入JVM時,就自動建立一個Class類的執行個體來表示這個類,也就是我們說的Class對象,收集了當前這個對象的基本資料,包括屬性、方法、構造器、介面、父類等。
注意:Class類沒有公用構造方法,Class對象是在載入類時由JVM以及類載入器中的defineClass()自動構造的。 所以Class類是類載入器的資訊來源者。
如何得到Class對象?
1.利用類名.Class方式直接獲得與指定關聯的Class對象,而並不需要有該類的對象存在。
樣本:
public class ReflactionTest {@Testpublic void testClass() throws ClassNotFoundException {Class clazz = null; //1.直接通過類名.class的方式得到clazz = Person.class; System.out.println(clazz); }
2.利用Object.getClass()方法擷取該方法對象所屬關聯的Class對象。
樣本:
public class ReflactionTest { @Test public void testClass() throws ClassNotFoundException { String str1 = new String(); String str2 = new String(); Class cl1= str1.getClass(); Class cl2 = str2.getClass(); System.out.println(cl1.getName());//得到類的完整名稱 System.out.println(cl1==cl2);}控制台輸出:
java.lang.String
true
上面代碼中,getClass方法用於返回封裝String類型的Class對象,getName返回封裝的類的名稱。同時cl1和cl2返回相同的對象,所以cl1==cl2返回true。
注意:對於相同的類,JVM只會載入一次,與該類對應的Class對象也只會存在一個,無論你執行個體化了幾個。
3.利用Class.forName()靜態方法,該方法根據指定的類名擷取與該類關聯的對象。如果該類還沒有被裝入,該方法會將該類裝入JVM。
樣本:
public class Person {public Person() {System.out.println("Person()");}static {System.out.println("Person is initialized");}}
運行下面的代碼:
public class ReflactionTest {@Testpublic void testNewInstance() throws ClassNotFoundException {String className = "com.tgb.reflectiontest.Person";Class clazz = Class.forName(className);}控制台輸出:
Person is initialized
Class.forName()方法,首先會將字串指定的類裝入JVM,並返回與之關聯的Class對象,JVM裝入後對其進行初始化,調用static塊中的代碼。 forName方法的參數必須要是類的完整指定名。
其他常用方法:
- getClassLoader(): 該方法用於返回該Class對象代表的類的類載入器。如果類的載入器為Bootstrap,則返回NUll.
- getSuperClass(): 該方法返回的是這個Class對象所代表的的JAVA類的父類對應的Classs對象。
- isArray() :判定此Class對象是否表示一個數組類。
- getInterfaces(): 確定此對象所表示的類或介面實現的介面。
- newInstance()方法使用所選的Class對象產生該類的新執行個體。它調用無參數的類構造器產生新的對象。對於newInstance()來說,可以在沒有任何對象存在的情況下,使用它建立一個新的對象。
樣本:
<pre name="code" class="java">public class ReflactionTest {@Testpublic void testNewInstance() throws ClassNotFoundException,InstantiationException, IllegalAccessException {String className = "com.tgb.reflectiontest.Person";Class clazz = Class.forName(className);Object obj = clazz.newInstance();System.out.println(obj);}}
上面代碼,首先使用Class.forName得到Class對象,即該方法要求JVM尋找並載入指定的Person類,並執行Person的靜態程式碼片段,動態載入和建立出Person對象。只有當執行了newInstance()方法時,才會執行個體化出一個對象來。
注意: 使用newInstance()建立的類必須有一個預設構造器。
總結:Class類總的來說也是一個類,這個類收集當前對象的基本資料(屬性、方法、構造器、父類、介面)。Class對象只能由系統建立,每個類只能有一個執行個體。 對於每個類而言,都有一個Class類型的對象來儲存這個類的資訊。
Class 和ClassLoader都是反射技術的基礎,需要我們掌握其原理。
Java反射基礎(二)— Class類