Class類是反射與加載器最常用的核心類,最近計劃寫一個JAVA加載器框架蹭越,決定重新溫習(xí)相關(guān)接口和類的源碼文檔障本,實踐相關(guān)用法以消除心中所存不確定。
- 目錄結(jié)構(gòu)
- 類說明
- 對象創(chuàng)建
- UML類圖
- 類成員方法
- 學(xué)習(xí)總結(jié)
1 類說明
翻譯Class類源碼英文文檔响鹃,分段翻譯并配合理解和例子加深印象驾霜。
英文:Instances of the class {@code Class} represent classes and interfaces in a running Java application.
中文:在一個運行中的JAVA程序,Class類的實例买置,代表用關(guān)鍵字class或interface聲明的對象粪糙,如public class AnyObject
與public interface AnyInterface
。
英文:An enum is a kind of class and an annotation is a kind of interface.
中文:Enum-枚舉是一種Class類型忿项,Annotation-注解是一種接口類型蓉冈。
英文:Every array also belongs to a class that is reflected as a {@code Class} object that is shared by all arrays with the same element type and number of dimensions.
中文:每一個數(shù)組屬于一個類,按照數(shù)組元素類型和維度被反射為一個類對象轩触,這個類對象被具有相同元素類型和維度的數(shù)組共享寞酿。
應(yīng)用理解
序號 | 變量聲明 | 變量聲明 | 是否相同 | 差異因素 |
---|---|---|---|---|
1 | String[] o1 = new String[3] | String[] o2 = new String[10] | 相同 | 無 |
2 | String[] o1 = new String[3] | String[][] o3 = new String[3][5] | 不同 | 數(shù)組維度 |
3 | String[] o1 = new String[3] | byte[] o4 = new byte[1024] | 不同 | 元素類型 |
英文:The primitive Java types ({@code boolean}, {@code byte}, {@code char}, {@code short},{@code int}, {@code long}, {@code float}, and {@code double}), and the keyword {@code void} are also represented as {@code Class} objects.
中文:JAVA原始類型boolean / byte / char / short / int / long / float / double 與void關(guān)鍵字,也都有一種類對象代表脱柱。
原始類型與類對象對應(yīng)表
序號 | 原始類型 | 對象類型 | 類型縮寫 |
---|---|---|---|
1 | boolean | java.lang.Boolean | Z |
2 | byte | java.lang.Byte | B |
3 | char | java.lang.Character | C |
4 | short | java.lang.Short | S |
5 | int | java.lang.Integer | I |
6 | long | java.lang.Long | J |
7 | float | java.lang.Float | F |
8 | double | java.lang.Double | D |
9 | void | java.lang.Void | V |
注意:原始類型與對象類型的Class不一樣伐弹,類型縮寫在.class文件中用到。另外褐捻,class或interface的類型縮寫為L掸茅。
2 對象創(chuàng)建
英文:{@code Class} has no public constructor. Instead {@code Class} objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the {@code defineClass} method in the class loader.
中文:Class沒有公有構(gòu)造器函數(shù),虛擬機裝載類對象或被調(diào)用ClassLoader的defineClass方法時柠逞,Class對象實例被JAVA虛擬機自動構(gòu)造昧狮。
Class對象實例的獲取方式
- 對象實例調(diào)用getClass方法
Thread thobj = new Thread();
Class clazz = thobj.getClass();
System.out.println(clazz.getName());
對任何對象類型的實例,調(diào)用getClass()函數(shù)可以獲取對象類型板壮。
- 類字面量.class方式
Class clazz = String.class;
System.out.println(clazz.getName());
類字面量逗鸣,就是指用class關(guān)鍵字聲明的對象名稱,如public class Foo {}
绰精,Foo
就是這個類的類字面量撒璧。
- 靜態(tài)函數(shù)forName
Class<?> clazz = Class.forName("java.lang.ArrayList");
請求參數(shù)為對象類型的全限定名稱,一般情況笨使,不需要額外制定類加載器卿樱。
- 泛型類型的獲取方式
Class<String> clazz = String.class
System.out.println(clazz.getName());
3 UML類圖
- Class類聲明
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {
//主體代碼
}
聲明分析
1 final關(guān)鍵字,Class類不能被繼承硫椰;
2 實現(xiàn)AnnotatedElement接口繁调,支持注解功能萨蚕;
3 支持泛型,Class<T>聲明蹄胰,實現(xiàn)GenericDeclaration岳遥,支持獲取泛型參數(shù)方法getTypeParameter;
4 實現(xiàn)Serializable接口裕寨,支持序列化浩蓉。
-
Class類圖
整理Class類實現(xiàn)的接口,依賴的類與接口宾袜。
ClassUML類圖.png
4 類成員方法
4.1 構(gòu)造函數(shù)
函數(shù)聲明:private Class(ClassLoader loader)
- 使用說明
不能直接用new生成Class實例捻艳,也不提默認(rèn)構(gòu)造函數(shù),直接由JVM在類裝載或ClassLoader調(diào)用defineClass是調(diào)用试和。
4.2 成員方法
4.2.1 forName方法
- 方法作用
靜態(tài)方法forName
通過類的全限定名稱加載類對象讯泣,常用于反射功能模塊。兩個函數(shù)的區(qū)別主要區(qū)別在于第二個函數(shù)制定了一個類加載器阅悍,函數(shù)實現(xiàn)時增加對加載器的安全權(quán)限檢查好渠。 - 方法聲明
public static Class<?> forName(String name) throws ClassNotFoundException
public static Class<?> forName(String name, bool isInit, ClassLoader loader) throws ClassNotFoundException
方法拋出異常還有LinkageError與ExceptionInInitializerError。
forName
底層調(diào)用靜態(tài)本地方法forName0
函數(shù):
private static native Class<?> forName0(String name, boolean isInit, ClassLoader loader, Caller<?> caller) throws ClassNotFoundException;
4.2.2 newInstance方法
- 方法作用
調(diào)用默認(rèn)構(gòu)造函數(shù)生成對象實例节视。 - 方法聲明
@CallerSensitive
public T newInstance() throws InstantiationException, IllegalAccessException
- 函數(shù)分析
注解@CallerSensitive拳锚,表明函數(shù)執(zhí)行是否成功與調(diào)用者權(quán)限有關(guān),Class類代碼首先調(diào)用系統(tǒng)安全管理器檢查調(diào)用者對本類是否有訪問權(quán)限寻行;
方法無參數(shù)霍掺,就是說,只能生成具有默認(rèn)無參構(gòu)造函數(shù)的類實例拌蜘;若需要調(diào)用含參數(shù)列表的構(gòu)造函數(shù)杆烁,需要通過反射技術(shù)調(diào)用Constructor類的newInstance方法;
4.2.3 isInstance方法
- 方法作用
判斷本類型是否繼承或?qū)崿F(xiàn)參數(shù)制定的類或接口简卧。 - 方法聲明
public native boolean isInstance(Object obj);
返回值說明
序號 | this類型 | obj說明 | 返回值 |
---|---|---|---|
1 | class | obj是該類對象實例或子類型實例 | true |
2 | array | obj能執(zhí)行類型轉(zhuǎn)換為array對象 | true |
3 | interface | obj的類或上級類實現(xiàn)此接口 | true |
4 | 原始類型 | 任何情況 | false |
4.2.4 isAssignedFrom方法
- 方法作用
判斷本類型是否為參數(shù)clazz的相同兔魂,或者是其子類或?qū)崿F(xiàn)類。 - 方法聲明
public native boolean isAssignedFrom(Class<?> clazz);
注意:與isInstance方法不同举娩,這個參數(shù)是Class類型析校,而isInstance的參數(shù)是對象實例。
4.2.5 常用判斷方法
public native boolean isInterface(); #判斷是否為接口對象
public native boolean isArray(); #判斷是否為數(shù)組對象
public native boolean isPrimitive(); #判斷是否為原始類型铜涉,如byte, int等
public boolean isAnnotation(); #判斷是否為注解類型
public boolean isSynthetic(); #判斷是否為合成類智玻,不是手動編寫的靜態(tài)類
public boolean isAnonymousClass(); #判斷是否為匿名類
public boolean isLocalClass(); #判斷是否為本地類
public boolean isMemberClass(); #判斷是否為成員類
public boolean isEnum(); #判斷是否為枚舉類型
4.2.6 字段操作方法
4.2.6.1 getField
- 方法作用
獲取類聲明的公有成員變量。 - 方法聲明
@CallerSensitive
public Field getField(String name);
根據(jù)名稱參數(shù)name
獲取類的同名字段芙代,沒有名稱對應(yīng)的字段將拋出NoSuchFieldException吊奢。
4.2.6.2 getFields
- 方法作用
獲取類聲明的所有公有成員變量,返回Field數(shù)組纹烹,沒有成員變量返回空數(shù)組页滚。 - 方法聲明
@CallerSensitive
public Field[] getFields() throws SecurityException;
4.2.6.3 getDeclaredField方法
- 方法作用
獲取類聲明的同名成員變量谬泌,不管是公有還是私有,沒有此名稱成員變量拋出異常逻谦。 - 方法申明
public Field getDeclaredField(String name);
4.2.6.4 getDeclaredFields方法
- 方法作用
獲取類聲明的所有成員變量,無論是公有還是私有陪蜻,無成員變量返回空數(shù)組邦马。
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException;
4.2.7 構(gòu)造器方法
4.2.7.1 getConstrucutor
- 方法作用
獲取與參數(shù)列表類型匹配的公有構(gòu)造函數(shù)宴卖。 - 方法申明
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException
4.2.7.2 getDeclaredConstructor
- 方法作用
獲取與參數(shù)列表類型匹配的構(gòu)造函數(shù)滋将,不論公有私有。 - 方法聲明
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException
4.2.7.3 getConstructors
- 方法作用
獲取類聲明的所有公有構(gòu)造函數(shù)症昏,返回Constructor數(shù)組随闽。 - 方法聲明
@CallerSensitive
public Constructor[] getConstructors() throws SecurityException;
4.2.7.4 getDeclaredConstructors
- 方法作用
獲取類聲明的所有構(gòu)造函數(shù),不論公有私有肝谭,返回Constructor數(shù)組掘宪。 - 方法聲明
@CallerSensitive
public Constructor[] getDeclaredConstructors() throws SecurityException;
4.2.8 成員方法函數(shù)
4.2.8.1 getMethod
- 方法作用
獲取與參數(shù)列表類型匹配的公有方法沙绝。 - 方法申明
@CallerSensitive
public Method getMethod(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException
4.2.8.2 getDeclaredMethod
- 方法作用
獲取與參數(shù)列表類型匹配的方法窄锅,不論公有私有爱谁。 - 方法聲明
@CallerSensitive
public Method getDeclaredMethod(Class<?>... paramTypes) throws NoSuchMethodException, SecurityException
4.2.8.3 getMethods
- 方法作用
獲取類聲明的所有公有方法一膨,返回Method數(shù)組横缔。 - 方法聲明
@CallerSensitive
public Method[] getMethods() throws SecurityException;
4.2.8.4 getDeclaredMethods
- 方法作用
獲取類聲明的所有方法渠抹,不論公有私有撵溃,返回Method數(shù)組邢笙。 - 方法聲明
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException;
4.2.9 getModifiers方法
- 方法作用
獲取類聲明的訪問修飾符芋齿,如public, protected, final等腥寇。 - 方法聲明
public native int getModifiers();
4.2.10 getInterfaces方法
- 方法作用
獲取類實現(xiàn)的接口列表數(shù)組,返回Class<?>數(shù)組觅捆, 沒有實現(xiàn)接口返回空數(shù)組赦役。 - 方法聲明
public Class<?>[] getInterfaces();
4.2.11 getClasses方法
- 方法作用
獲取類繼承或?qū)崿F(xiàn)接口的數(shù)組,返回Class<?>數(shù)組惠拭, 沒有集成與實現(xiàn)接口返回空數(shù)組扩劝。 - 方法聲明
public Class<?> getClasses();
注意:getClasses方法包含getInterfaces方法返回的接口數(shù)組,排序與源代碼聲明順序一致职辅。
4.2.12 getSuperclass方法
- 方法作用
獲取類的父類型棒呛,Class代表的類型可以是class / interface / 原始類型 / void。 - 方法聲明
public native Class<? super T> getSuperclass();
- 返回值說明
如果this是原始類型域携,父類型返回null簇秒;如果this代表一個數(shù)組,父類型返回java.lang.Object秀鞭。
4.2.13 getPackage方法
- 方法作用
返回類所在的包對象趋观。 - 方法聲明
public Package getPackage();
4.2.14 getComponentType方法
- 方法作用
獲取數(shù)組元素類型扛禽,如果this不是數(shù)組類型,返回null皱坛。 - 方法聲明
public native Class<?> getComponentType()
- 應(yīng)用示例
數(shù)組String[]编曼,函數(shù)返回數(shù)組元素類型java.lang.String。
4.2.15 getName方法
- 方法作用
獲取this對象的全限定名稱剩辟。 - 方法聲明
public String getName();
- 應(yīng)用示例
- 對象類型掐场,如String.class.getName(),返回名稱為java.lang.String贩猎;
- 原始類型熊户,如byte.class.getName(),返回名稱與原始類型一樣吭服,這里返回"byte"嚷堡;
- 數(shù)組類型,分兩種情況:1)原始類型數(shù)組艇棕,返回“前綴[ + 類型縮寫"蝌戒,如byte[5],返回字符串”[B“沼琉;2)對象數(shù)組瓶颠,返回前綴[ + 類型全限定名稱”,如String[5]刺桃, 返回[Ljava.lang.String粹淋;
- 多維數(shù)組,與數(shù)組類型格式一致瑟慈,數(shù)組有幾維桃移、就有幾個前綴[,如long[2][3][4][5]葛碧,返回字符串“[[[[J”借杰;
4.2.16 注解操作方法
Spring / MyBatis就是調(diào)用Class類的注解操作方法,解析BEAN對象等的注解配置的进泼,研究框架得多了解下這幾個函數(shù)蔗衡。
4.2.16.1 getAnnotation方法
- 方法作用
根據(jù)注解的類型獲取類聲明的注解對象。 - 方法聲明
public <A extends Annotation> A getAnnotation(Class<A> annotationType);
- 使用示例
@RestController("/message")
class MessageController {
@RequestMapping(value="annotation")
public String getAnnotation(){
RestController obj =(RestController)this.getClass().getAnnotation(RestController.class);
System.out.println(obj.value());
return obj.value();
}
}
4.2.16.2 getAnnotations方法
- 方法作用
獲取類聲明的所有注解對象乳绕,返回Annotation數(shù)組绞惦,沒有注解返回空數(shù)組。 - 方法聲明
public Annotation[] getAnnotations();
4.2.16.3 isAnnotationPresent方法
- 方法作用
返回類是否聲明annotationType參數(shù)指定的注解洋措。 - 方法聲明
public boolean isAnnotationPresent(Annotation<? extends Annotation> annotationType) ;
- 方法示例
@Deprecated
public class App{
public static void main(String[] args){
/* 判斷App類是否被Deprecated注解標(biāo)識成Deprecated */
boolean isOld = App.class.isAnnotationPresent(Deprecated.class);
}
}
4.2.16.4 getAnnotationsByType方法
- 方法作用
根據(jù)注解類型annotationType獲取類聲明的所有注解济蝉,返回Annotion[]。 - 方法聲明
public <A extends Annotation> A[] getAnnotationsByType(Class<A extends Annotation> annotationType)
4.3 其它函數(shù)
Class類的方法還有不少,尤其是要研究幾個內(nèi)部類的作用王滤,如EnclosingMethodInfo贺嫂、ReflectionData等,了解其緩存優(yōu)化等特點雁乡。
5 學(xué)習(xí)總結(jié)
Class類是反射技術(shù)的核心類
掌握forName方法使用第喳,熟練使用構(gòu)造函數(shù)、成員變量踱稍、成員變量獲取函數(shù)
了解getSuperclass墩弯、getClasses與getInterfaces方法使用,動態(tài)代理過程常用
熟悉注解對象操作函數(shù)寞射,框架對象屬性配置經(jīng)常用到