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實例,也不提默認構(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)用默認構(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ù),就是說,只能生成具有默認無參構(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注解標識成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)常用到
