玩轉java(2)— 泛型type體系與反射

來源:互聯網
上載者:User

一、Type類型

Type是Java程式設計語言中所有類型的普通的父介面。這些類型包括原生類型(raw types),參數化型別(parameterized types),數群組類型(array types),類型變數(type variables)和 原始類型(primitive types)。我們一般不直接操作Type類型,但瞭解一下Type類型的階層還是有必要的。

1、Type階層


2、Class,Method和Field的繼承體系


二、Type與反射

反射機制允許程式在運行時取得任何一個已知名稱的class的內部資訊,容許程式在運行時載入、探知、使用編譯期間未知的class。即Java的反射機制可以載入一個運行時才得知名稱的class,獲得其完整結構。

1、反射的基礎:Class

在程式運行期間,Java運行時系統始終為所有的對象維護一個被稱為運行時的類型標識。這個資訊儲存著每個對象所屬的類足跡。虛擬機器利用運行時資訊選擇相應的方法執行。然而,可以通過專門的Java類訪問這些資訊。儲存這些資訊的類稱為Class,泛型形式為Class<T>。Class是反射機制的基礎,反射API通過操作Class來擷取其完整結構。

擷取Class的常用方式:

調用getClass()(Object類中的getClass()方法返回一個Class類型的執行個體)

Boolean var1 = true;Class<?> classType2 = var1.getClass();System.out.println(classType2);輸出:class java.lang.Boolean 

運用T.class 文法(T是任意的Java類型)

Class<?> classType4 = Boolean.class;System.out.println(classType4);輸出:class java.lang.Boolean 

運用static method Class.forName()(使用時應該提供異常處理器)

Class<?> classType5 = Class.forName("java.lang.Boolean");System.out.println(classType5);輸出:class java.lang.Boolean 

運用primitive wrapper classes的TYPE 文法(這裡返回的是原生類型,和Boolean.class返回的不同)

Class<?> classType3 = Boolean.TYPE;System.out.println(classType3);輸出:boolean 


註:一個Class對象實際上表示的是一個類型,而這個類型未必一定是一種類。例如,int不是類,但int.class是一個Class類型的對象。虛擬機器為每個類型管理一個Class對象。因此,可以用==運算子實現兩個類對象比較的操作。 Class常用的方法:

方法

說明

例子

getName()

 

返回類的名字

String.class.getName();

返回: "java.lang.String"

newInstance()

 

快速地建立一個類的執行個體(調用預設構造器,如果該類沒有預設構造器,拋出異常)(如果要為構造器提供參數,使java.lang.reflect.Constructor中的newInstance方法)

String s = "java.util.Date";

Object m = Class.forName(s).newInstance();

getSuperclass()

返回超類

 

getFields() getMethods() getConstructors()(還有帶字串參數,給定名稱的形式)

分別返回類支援的public域、方法和構造器數組,其中包括超類的公有成員

 

getDeclaredFields()

getDeclaredMethods()

getDeclaredConstructors()(還有給定名稱的形式)

分別返回類中聲明的全部域、方法和構造器數組。其中包括私人和保護成員,但不包括超類的成員

 


2、使用反射分析類

一個類主要由修飾符,域,構造器,方法組成,而 Field、Method、Constructor類,分別用於描述類的域、方法和構造器。另外java.lang.reflect包中的Modifier類可以分析存取修飾詞。那麼用它們就可以分析類。

分析類常用的方法:

方法 作用
Field
Method
Constructor
Class getDeclaringClass() 返回一個用於描述類中定義的構造器、方法或域的Class對象
String getName() 返回相應條目的名稱
int getModifiers() 返回整型數值,用不同的位開關描述存取修飾詞的使用狀況

Method

Constructor

Class[] getExceptionTypes()

返回一個用於描述方法拋出的異常類型的Class對象數組

Class[] getParameterTypes()

返回一個用於描述參數類型的Class對象數組

Field

Class getType()

用於返回描述域所屬類型的Class類型對象

Modifier

static String toString(int modifiers)

返回對應modifiers位設定的修飾符的字串表示

Static boolean isXXX(int modifiers)

檢測方法名中對應的修飾符在modifiers中的值

存取權限問題:

由於反射機制的預設行為受限於Java的存取控制,比如,訪問私人的方法,欄位,除非擁有存取權限,否則Java安全機制允許查看任意對象有哪些域,而不允許讀它們的值(讀取將拋異常)。然而如果一個Java程式沒有受到安全管理器的控制,就可以覆蓋存取控制。為了達到這個目的,就需要調用Field、Method、Constructor對象的setAccessible()方法。

函數

作用

void setAccessible(boolean flag)

為反射對象設定可訪問標誌,flag為true表明屏蔽Java語言的訪問檢查,使得對象的私人屬性也可以被查詢和設定

boolean isAccessible()

返回反射對象的可訪問標誌的值

static void setAccessible(AccessibleObject[] array, boolean flag)

一種設定對象數組可訪問標誌的快捷方法

3、一個經典的反射工具類

package study.java.core.util;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * 反射工具類 * @author qbg * */public abstract class ReflectUtil {/** * 擷取某個對象的屬性 */public Object getProperty(Object owner,String fieldName) throws Exception {//1、得到該對象的Class。Class<?> ownerClass = owner.getClass();//2、通過Class得到類聲明的屬性。Field field = ownerClass.getField(fieldName);//3、通過對象得到該屬性的執行個體,如果這個屬性是私人的,這裡就會拋出IllegalAccessException。Object property = field.get(owner); //此處擷取的是對象的屬性,所以傳遞的是owner。return property;}/** * 擷取某個類的靜態屬性 */public Object getStaticProperty(String className,String fieldName) throws Exception{//1、得到該類的Class。Class<?> ownerClass = Class.forName(className);//2、通過Class得到類聲明的屬性。Field field = ownerClass.getField(fieldName);//3、由於擷取的是靜態屬性,此處傳遞的為Class,直接從Class中擷取靜態屬性。Object property = field.get(ownerClass); return property;}/** * 執行某對象的方法 */public Object invokeMethod(Object owner,String methodName,Object[] args) throws Exception{//1、擷取對象的Class。Class<?> ownerClass = owner.getClass();//2、組裝參數的Class數組,用於匹配Method的條件Class<?>[] argsClass = new Class<?>[args.length];for(int i=0; i<args.length; i++){argsClass[i] = args[i].getClass();}//3、通過Method名和參數的Class數組得到要執行的MethodMethod method = ownerClass.getMethod(methodName, argsClass);//4、調用invoke執行Method.由於執行的是對象的方法,此處傳遞的為owner。return method.invoke(owner, args);}/** * 執行類的靜態方法 */public Object invokeStaticMethod(String className,String methodName,Object[] args) throws Exception{//1、擷取類的Class。Class<?> ownerClass = Class.forName(className);//2、組裝參數的Class數組,用於匹配Method的條件Class<?>[] argsClass = new Class<?>[args.length];for(int i=0; i<args.length; i++){argsClass[i] = args[i].getClass();}//3、通過Method名和參數的Class數組得到要執行的MethodMethod method = ownerClass.getMethod(methodName, argsClass);//4、調用invoke執行Method.由於執行的是類的靜態方法,不需要藉助對象執行個體,此處傳遞的為null。return method.invoke(null, args);}/** * 建立執行個體。調用帶參建構函式。 */public Object newInstance(String className,Object[] args) throws Exception{//1、擷取要構造執行個體的ClassClass<?> newOneClass = Class.forName(className);//2、得到參數的Class數組Class<?>[] argsClass = new Class<?>[args.length];for(int i=0; i<args.length; i++){argsClass[i] = args[i].getClass(); }//3、得到構造器Constructor<?> ctor = newOneClass.getConstructor(argsClass);//4、建立執行個體return ctor.newInstance(args);}/** * 判斷是否為某個類的執行個體 */public boolean isInstance(Object obj,Class<?> clazz){return clazz.isInstance(obj);}/** * 得到數組中的某個元素 */public Object getByArray(Object array,int index){return Array.get(array, index);}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.