標籤:
看到Class的時候,我們是不是會一下子想到我們寫程式中的class呢?此Class非彼class,這裡講的Class類實際上就是java類的統稱,我們可以將其稱之為抽象的類不是具體的一個類的名字。
1. 概念
Java程式中的各個java類屬於同一個事物,描述這類事物的java類名就是Class。也許這個解釋還是不夠清晰,再細點說:
Java類用於描述一類事物的共性,該類事物有什麼屬性,沒有什麼屬性,至於這個屬性的值是什麼,則是由這個類的執行個體對象來確定的,不同的執行個體對象有不同的屬性值,java程式中的各個java類,他們是否屬於同一類事物,是不是可以用一個類來描述這個類事物呢?那麼這個類的名字就是Class。
值得注意:不同於小寫class.Class類描述了類的名字,類的訪問屬性,類所屬於的包名,欄位名稱的列表,方法名稱的列表等等,這是反射的基礎。
2. 本質解析
舉個簡單的例子來解釋:人的名字是person,那麼java類的名字就是Class。
我們如果將人進行執行個體化,那麼其執行個體化對象則是張三或者李四等等,Class類代表一個個的java類,那麼它的各個執行個體對象又是什麼呢?
Class類的執行個體對象對應的是各個類在記憶體中的位元組碼,例如,person類的位元組碼,Date類的位元組碼等等。一個類被類載入器載入到記憶體中,佔用一片儲存空間,這個空間裡面的內容就是類的位元組碼,不用的類的位元組碼是不同的,所有它們在記憶體中的內容是不同的。那麼具體什麼是位元組碼嗎?
3. 位元組碼 ? 定義
當我們在來源程式中用到了person類的時候,首先需要在硬碟上將這個類的二進位代碼編譯成Class放在硬碟上,就是一群二進位代碼,需要將這群二進位代碼載入到記憶體中來,才可以使用它建立一個個的對象,首先要將類的位元組碼載入到記憶體中來,再用這個位元組碼去讀取一個個的對象來,當程式中用到了好多個類的時候,那麼記憶體中就應該存在幾個位元組碼,每一份位元組碼就是一個Class的執行個體對象。
我們知道對於之前我們見過的類比如person,當我們用其對象時,可以使用:
Person p1=newPerson();但是Class是不能直接用new Class直接擷取到的,比如
Class cs1=位元組碼;cs1代表記憶體中的一個位元組碼,比如說我們將其對應相應的對象,則是
Classcs1=Date.class;//位元組碼1
Classcs2=Person.class;//位元組碼2
? 如何得到位元組碼
通常情況下我們可以採用三種方式擷取到位元組碼:
第一種類名.class 比如:System.class
舉個例子:Classcls1=Date.class;//位元組碼;這裡採用的Date就是一個類,我們經常使用的String等等並不是原始的基礎資料型別 (Elementary Data Type),而是類,通常情況下存在八種基礎資料型別 (Elementary Data Type),分別是boolean、byte、char、short、int、long、float anddouble。
第二種對象.getClass() 比如:new Date().getClass()
以上面的例子為例,比如 Person p1=new Person();那麼P1就是一個執行個體化的對象也是P1位元組碼得到的具體的對象,這樣我們就去拿到它的位元組碼,也就是p1.getClass();
第三種Class.forName(“類名”) 比如:Class. forName(“java.util.Date”);
此外Class這個類還存在一個靜態方法那就是forName();括弧中的類名必須指定的是完整的類名,比如Class. forName(“java.util.String”);這也是相當於將抽象類別找到具體的類,也就是String類的位元組碼;如果這個類本身已經載入到記憶體中來了,那麼就不需要再次進行載入了.
forName的作用是返回位元組碼,返回方式存在兩種:
1、 這份位元組碼曾經被載入過,已經呆在載入器裡面了,那麼直接返回即可。
2、 Java虛擬機器中還沒有這個位元組碼,則用內載入器去載入,把載入進來的位元組程式碼快取在虛擬機器中,以後要得到這份位元組碼就不用再載入了。
三種方式最優的是Class.forName();
第三種的好處是動態編譯的而不是靜態,前兩者都是在編譯的時候已經確定了類型,但是第三種可以在啟動並執行時候進行配置,因為是字串,那麼我們可以定義一個變數進行儲存,也就是說在設定檔中啟動並執行時候動態給其賦值。
值得注意:以上三種方式均是可以得到位元組碼,並且三種擷取位元組碼的方式在記憶體中實際上是同一份位元組碼。
String str1 = "abc";Class cls1 = str1.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String");System.out.println(cls1 == cls2);System.out.println(cls1 == cls3);
列印的結果均為true,說明三種擷取位元組碼的方式在記憶體中實際上是同一份位元組碼。
Ps:判斷一種類型是不是基礎資料型別 (Elementary Data Type),通常情況下我們可以這樣的代碼進行判斷;int.class.isPrimitive();此外我們還可以使用:int.class==Integer.TYPE來查看是否是基礎資料型別 (Elementary Data Type)。
Type屬性同樣適用於其他的類比如Boolean.TYPE,Character.TYPE,Byte.TYPE,Short.TYPE,Integer.TYPE,Long.TYPE,Float.TYPE,Double.TYPE,Void.TYPE。
4. 小結
瞭解Class類為我們瞭解反射機制奠定了基礎,這是學習反射的前提。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java之旅(1)—Class類