Java基礎-Class類,java基礎-class
java的Class類是java反射機制的基礎,通過Class類我們可以獲得關於一個類的相關資訊,下面我們來瞭解一下有關java中Class類的相關知識!
java.lang.Class是一個比較特殊的類,它用於封裝被裝入到JVM中的類(包括類和介面)的資訊。
當一個類或介面被裝入的JVM時便會產生一個與之關聯的java.lang.Class對象,可以通過這個Class對象對被裝入類的詳細資料進行訪問。
簡單的說,擷取某一個類所對應的Class對象可以通過如下三種途徑:
1. Object的getClass方法
java.lang.Object中定義有getClass方法:
public final Class getClass()
所有Java對象都具備這個方法。該方法用於返回與調用該方法對象所屬類關聯的Class對象,例如:
Date date1 = new Date();
Date date2 = new Date();
Class c1 = date1.getClass();
Class c2 = date2.getClass();
System.out.println(c1.getName()); // java.util.Date
System.out.println(c1 == c2); // true
上面的代碼中,調用Date對象date1的getClass方法將返回用於封裝Date類資訊的Class對象。這裡調用了Class類的getName方法:
public String getName()
這個方法的含義很直觀,即返回所封裝的類的名稱。
需要注意的是,代碼中的date1和date2的getClass方法返回了相同的Class對象(c1==c2的值為true)。這是因為,對於相同的類,JVM只會載入一次,而與該類對應的Class對象也只會存在一個,無論該類執行個體化了多少對象。
另外,需要強調的是,當一個對象被其父類的引用或其實現的介面類型的引用所指向的時,getClass方法返回的是與對象實際所屬類關聯的Class對象。例如:
List list = new ArrayList();
System.out.println(list.getClass().getName()); // java.util.ArrayList
上面的代碼中,語句list.getClass()方法返回的是list所指向對象實際所屬類java.util.ArrayList對應的 Class對象而並未java.util.List所對應的Class對象。有些時候可以通過這個方法瞭解一個對象的運行時類型,例如:
HashSet set = new HashSet();
Iterator it = set.iterator();
System.out.println(it.getClass().getName()); //java.util.HashMap$KeyIterator
從代碼可以看出,HashSet的iterator方法返回的是實現了Iterator介面的HashMap內部類(KeyIterator)對象。
因為抽象類別和介面不可能執行個體化對象,因此不能通過Object的getClass方法獲得與抽象類別和介面關聯的Class對象。
2. 使用.class的方式
使用類名加“.class”的方式即會返回與該類對應的Class對象。例如:
Class clazz = String.class;
System.out.println(clazz.getName()); // java.lang.String
這個方法可以直接獲得與指定類關聯的Class對象,而並不需要有該類的對象存在。
3. 使用Class.forName方法
Class有一個著名的static方法forName:
public static Class forName(String className) throws ClassNotFoundException
該方法可以根據字串參數所指定的類名擷取與該類關聯的Class對象。如果該類還沒有被裝入,該方法會將該類裝入JVM。
該方法聲明拋出ClassNotFoundException異常。顧名思義,當該方法無法擷取需要裝入的類時(例如,在當前類路徑中不存在這個類),就會拋出這個異常。
例如,如果當前類路徑中存在Foo類:
package org.whatisjava.reflect;
public class Foo {
public Foo() {
System.out.println("Foo()");
}
static {
System.out.println("Foo is initialized");
}
}
運行下面的代碼:
Class clazz = Class.forName("org.whatisjava.reflect.Foo");
控制台會有如下輸出:
Foo is initialized
Class.forName("org.whatisjava.reflect.Foo")首先會將reflection.Foo類裝入JVM,並 返回與之關聯的Class對象。JVM裝入Foo類後對其進行初始化,調用了其static塊中的代碼。需要注意的是:forName方法的參數是類的完 整限定名(即包含包名)。
區別於前面兩種擷取Class對象的方法。使用Class.forName方法所要擷取的與之對應的Class對象的類可以通過字串的方式給定。該方法通常用於在程式運行時根據類名動態載入該類並獲得與之對應的Class對象。
通過上面的文章相信你對java的反射機制有了一定的認識,同時也對java中Class類的用法有了比較清晰的理解,在我們實際工作的過程中,我們不斷的運用java知識來解決實際生湖中的問題的時候我們就能對java反射機制有一個更深入的理解!
Java程式在運行時,Java運行時系統一直對所有的對象進行所謂的運行時類型標識。這項資訊紀錄了每個對象所屬的類。虛擬機器通常使用運行時類型資訊選准正確方法去執行,用來儲存這些類型資訊的類是Class類。Class類封裝一個對象和介面運行時的狀態,當裝載類時,Class類型的對象自動建立。
Class 沒有公用構造方法。Class 對象是在載入類時由 JAVA 虛擬機器以及通過調用類載入器中的 defineClass 方法自動構造的,因此不能顯式地聲明一個Class對象。
虛擬機器為每種類型管理一個獨一無二的Class對象。也就是說,每個類(型)都有一個Class對象。運行程式時,Java虛擬機器(JVM)首先檢查是否所要載入的類對應的Class對象是否已經載入。如果沒有載入,JVM就會根據類名尋找.class檔案,並將其Class對象載入。
基本的 Java 類型(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也都對應一個 Class 對象。
每個數組屬於被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共用該 Class 對象。
一般某個類的Class對象被載入記憶體,它就用來建立這個類的所有對象。
一、如何得到Class的對象呢?有三種方法可以的擷取:
1、調用Object類的getClass()方法來得到Class對象,這也是最常見的產生Class對象的方法。例如:
MyObject x;
Class c1 = x.getClass();
2、使用Class類的中靜態forName()方法獲得與字串對應的Class對象。例如:
Class c2=Class.forName("MyObject"),Employee必須是介面或者類的名字。
3、擷取Class類型對象的第三個方法非常簡單。如果T是一個Java類型,那麼T.class就代表了匹配的類對象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
注意:Class對象實際上描述的只是類型,而這類型未必是類或者介面。例如上面的int.class是一個Class類型的對象。由於曆史原因,數群組類型的getName方法會返回奇怪的名字。二、Class類的常用方法
1、getName()
一個Class對象描述了一個特定類的屬性,Class類中最常用的方法getName以 String 的形式返回此 Class 對象所表示的實體(類、介面、數組類、基本類型或 void)名稱。 2、newInstance()
Class還有一個有用的方法可以為類建立一個執行個體,這個方法叫做newInstance()。例如:
x.getClass.newInstance(),建立了一個同x一樣類型的新執行個體。newInstance()方法調用預設構造器(無參數構造器)初始化建立對象。 3、getClassLoader()
返回該類的類載入器。 4、getComponentType()
返回表示數組組件類型的 Class。 5、getSuperclass()
返回表示此 Class 所表示的實體(類、介面、基本類型或 void)的超類的 Class。 6、isArray()
判定此 Class 對象是否表示一個數組類。三、Class的一些提示
1、forName和newInstance結合起來使用,可以根據儲存在字串中的類名建立對象。例如
Object obj = Class.forName(s).newInstance(); 2、虛擬機器為每種類型管理一個獨一無二的Class對象。因此可以使用==操作符來比較類對象。例如:
if(e.getClass() == Employee.class)...
Class類(在java.lang包中,Instances of the class Classrepresent classes and interfaces in a running Javaapplication):
在Java中,每個class都有一個相應的Class對象。也就是說,當我們編寫一個類,編譯完成後,在產生的.class檔案中,就會產生一個Class對象,用於表示這個類的類型資訊
擷取Class執行個體的三種方式:
(1)利用對象調用getClass()方法擷取該對象的Class執行個體;
(2)使用Class類的靜態方法forName(),用類的名字擷取一個Class執行個體(staticClass forName(String className) Returns the Classobject associated with the class or interface with the given stringname. );
(3)運用.class的方式來擷取Class執行個體,對於基礎資料型別 (Elementary Data Type)的封裝類,還可以採用.TYPE來擷取相對應的基礎資料型別 (Elementary Data Type)的Class執行個體
在newInstance()調用類中預設的構造方法 ObjectnewInstance()(可在不知該類的名字的時候,常見這個類的執行個體) Creates a new instance of the class represented by this Classobject.
在運行期間,如果我們要產生某個類的對象,Java虛擬機器(JVM)會檢查該類型的Class對象是否已被載入。如果沒有被載入,JVM會根據類的名稱找到.class檔案並載入它。一旦某個類型的Class對象已被載入到記憶體,就可以用它來產生該類型的所有對象
1 public class ClassTest {
2 public static void main(String [] args)throws Exception{
3 String str1="abc";
4 Class cls1=str1.getClass();
5 Class cls2=String.class;
6 Class cls3=Class.forName("java.lang.String");
7 System.out.println(cls1==cls2);
8 System.out.println(cls1==cls3);
9 }
10 }
返回結果為:true,true.
解釋:虛擬機器只會產生一份位元組碼, 用這份位元組碼可以產生多個執行個體對象。
反射
反射就是把Java類中的各種成分映射成相應的java類。例如,一個Java類中用一個Class類的對象來表示,一個類中的組成部分:成員變數,方法,構造方法,包等等資訊也用一個個的Java類來表示,就像汽車是一個類,汽車中的發動機,變速箱等等也是一個個的類。表示Java類的Class類顯示要提供一系列的方法,來獲得其中的變數,方法,構造方法,修飾符,包等資訊,這些資訊就是用相應類的執行個體對象來表示,它們是Field、Method、Contructor、Package等等。
一個類中的每個成員都可以用相應的反射API類的一個執行個體對象來表示,通過調用Class類的方法可以的得到這些執行個體對象後,得到這些執行個體對象後有什麼用呢?怎麼用呢?這正是學習和應用反射的要點。
構造方法的反射應用
Consturctor(構造器)類代表某個類中的一個構造方法
@1@ 得到某個類所有的構造方法:例如:Constructor [] constructors = Class.forName("java.lang.String").getConstructors();
@2@ 得到某一個構造方法:例如:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
@3@ 建立執行個體對象:通常方式:String str=new String(new StringBuffer("abc"));
反射方式:String str=(String) constructor.newInstance(new StringBuffer("abc"));
Class 類是在Java語言中 定義一個特定類的實現。一個類的定義包含成員變數,成員方法,還有這個類實現的介面,以及這個類的父類。Class類的對象用於表示當前啟動並執行 Java 應用程式中的類和介面。 比如:每個數組均屬於一個 Class 類對象,所有具有相同元素類型和維數的數組共用一個Class 對象。基本的 Java 類型(boolean, byte, char, short, int, long, float 和 double) 和 void 類型也可表示為 Class 對象。
以下樣本使用 Class 對象顯示一個對象的 Class 名:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
我們都知道所有的java類都是繼承了object這個類,在object這個類中有一個方法:getclass().這個方法是用來取得該類已經被執行個體化了的對象的該類的引用,這個引用指向的是Class類的對象(呵呵,有點彆扭)。我們自己無法產生一個Class對象(建構函式為private),而 這個Class類的對象是在當各類被調入時,由 JAVA 虛擬機器自動建立 Class 對象,或通過類裝載器中的 defineClass 方法產生。我們產生的對象都會有個欄位記錄該對象所屬類在CLass類的對象的所在位置。如所示:
Class類
我們可以把每個Class類的對象當做眾多類的代理。而且在每個Class類對象中有會有欄位記錄他引用的這個類的類載入器。如果該欄位為null,表示該類的載入器為bootstrap loader.具體原因見:對於類載入器的認識一文。
我們知道java中有多個載入器,每個載入器能載入多個類,所以只要取得Class類對象,就可利用其getClassLoader()方法取得該類載入器的引用。
jvm為每種類管理者獨一的Class對象。因此我們可以用雙等號操作符來比較對象:a1.getClass()==A.class;應該返回的是true。
class類和載入器
forName(String classname)和 forName(String classname,boolean initialze,ClassLoader loader) 方法
該方法返回給定串名相應的de>Classde> 對象。若給定一個類或介面的完整路徑名,那麼此方法將試圖定位、裝載和串連該類。若成功,返回該類對象。否則,拋出 ClassNotFoundException 異常。 例如,下面程式碼片段返回名為de>java.lang.Threadde> 的運行 de>Classde> 描述器。de>Class t = Class.forName("java.lang.Thread") ; 此方法是需要指定類載入器的,當用到僅有一個String參數的 forName方法時,Class對象將預設調用當前類載入器作為載入器和將第二參數為 true。第二個參數說明:如果是false時,調用forName方法只是在命令類載入器載入該類,而不初始化該類的靜態區塊,只有當該類第一次執行個體化 時,靜態區塊才被調用。當為true時,則載入時就調用靜態區塊。 de>
getClassLoader()
擷取該類的類裝載器。
getComponentType()
如果當前類表示一個數組,則返回表示該數組組件的 Class 對象,否則返回 null。
getConstructor(Class[])
返回當前 Class 對象表示的類的指定的公有構造子物件。
getConstructors()
返回當前 Class 對象表示的類的所有公有構造子物件數組。
getDeclaredConstructor(Class[])
返回當前 Class 對象表示的類的指定已說明的一個構造子物件。
getDeclaredConstructors()
返回當前 Class 對象表示的類的所有已說明的構造子物件數組。
getDeclaredField(String)
返回當前 Class 對象表示的類或介面的指定已說明的一個域對象。
getDeclaredFields()
返回當前 Class 對象表示的類或介面的所有已說明的域對象數組。
getDeclaredMethod(String, Class[])
返回當前 Class 對象表示的類或介面的指定已說明的一個方法對象。
getDeclaredMethods()
返回 Class 對象表示的類或介面的所有已說明的方法數組。
getField(String)
返回當前 Class 對象表示的類或介面的指定的公有成員域對象。
getFields()
返回當前 Class 對象表示的類或介面的所有可訪問的公有域對象數組。
getInterfaces()
返回當前對象表示的類或介面實現的介面。
getMethod(String, Class[])
返回當前 Class 對象表示的類或介面的指定的公有成員方法對象。
getMethods()
返回當前 Class 對象表示的類或介面的所有公有成員方法對象數組,包括已聲明的和從父類繼承的方法。
getModifiers()
返回該類或介面的 Java 語言修改器代碼。
getName()
返回 Class 對象表示的類型(類、介面、數組或基底類型)的完整路徑名字串。
getResource(String)
按指定名尋找資源。
getResourceAsStream(String)
用給定名尋找資源。
getSigners()
擷取類標記。
getSuperclass()
如果此對象表示除 Object 外的任一類, 那麼返回此對象的父類對象。
isArray()
如果 Class 對象表示一個數組則返回 true, 否則返回 false。
isAssignableFrom(Class)
判定 Class 對象表示的類或介面是否同參數指定的 Class 表示的類或介面相同,或是其父類。
isInstance(Object)
此方法是 Java 語言 instanceof 操作的動態等價方法。
isInterface()
判定指定的 Class 對象是否表示一個介面類型。
isPrimitive()
判定指定的 Class 對象是否表示一個 Java 的基底類型。
newInstance()
建立類的新執行個體。
toString()
將對象轉換為字串。