反射機制的概念
在 前一篇中其實有提到過反射機制相關的概念了,隻是沒有正式說明,在這裡我覺得有必需認真地說明一下。反射就是指在程式運作的時候,對于任何一個類,都可以得到這個類的屬性或是方法;對于任何一個對象,都可以調用這個對象的方法和屬性。(出自百度百科)
今天的主角:Constructor
上一篇我們了解到每一個類的資訊都有一個抽象的類--Class ,那麼再細化下去,類中的構造方法這麼重要且特别的存在也肯定有對應的東西去抽象它,那就是我們今天的主角 java.lang.reflect.Constructor<T>。
它就是抽象我們的構造方法的,那麼我們如何獲得這個類的執行個體呢,通過查詢 Class 類的方法可以得知有兩個方法可以得到構造函數的對象:
getConstructors() 和 getConstructor(Class<?>... parameterTypes) 前都傳回的是所有的構造方法對象,也是構造方法數組;後者則傳回與 Class<?>... parameterTypes 相同入參的構造方法對象。
在這裡我建了兩個測試類如下 package com.hlmtest.java.reflect; public class TestClass { private String str1 ; private String str2 ; public TestClass(){} public TestClass(String str1 ,String str2 ){ this . str1 = str1 ; this . str2 = str2 ; } public String getStr1() { return str1 ; } public void setStr1(String str1 ) { this . str1 = str1 ; } public String getStr2() { return str2 ; } public void setStr2(String str2 ) { this . str2 = str2 ; } public String toString(){ return "str1:" + str1 + ";str2" + str2 ; } } package com.hlmtest.java.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class TestAccessibleObject { public static void main(String[] args ) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { getConstructor();
} public static void getConstructor() throws NoSuchMethodException, SecurityException{ Class<TestClass> clzz = TestClass. class ; @SuppressWarnings ( "rawtypes" ) //構造方法數組 Constructor[] conList = clzz .getConstructors(); for (Constructor<?> r : conList ){ System. out .println( r .toGenericString()); } @SuppressWarnings ( "rawtypes" ) Class[] str = {String. class ,String. class }; //後者則傳回兩個及參對象的構造方法對象 Constructor<TestClass> con = clzz .getConstructor( str ); System. out .println( con .toGenericString()); @SuppressWarnings ( "rawtypes" ) Class[] str1 = {String. class ,String. class ,String. class }; //沒有入參為三個參數的構造方法,是以這裡會報 NoSuchMethodException 錯誤, //為了能列印我在這裡有預見性地把異常截住了 try { @SuppressWarnings ( "unused" ) Constructor<TestClass> con1 = clzz .getConstructor( str1 ); System. out .println( "沒有入參為三個參數的構造方法!" ); } catch (NoSuchMethodException e ){ System. out .println( e ); System. out .println( "沒有入參為三個參數的構造方法!" ); } } }
執行 TestAccessibleObject的main 方法得到的結果為: public com.hlmtest.java.reflect.TestClass() public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String) public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String) java.lang.NoSuchMethodException : com.hlmtest.java.reflect.TestClass.<init>(java.lang.String, java.lang.String, java.lang.String) 沒有入參為三個參數的構造方法! (Constructor類中還有很多其他方法,在些我就不一一舉例了,畢竟今天的主要任務是通過構造方法的執行個體來擷取主類的執行個體。大不了我在後面貼一下api的網址嘛)
下面的代碼是在上面的代碼基礎上添加一個利用構造方法執行個體來獲得主類執行個體對象的方法,為了友善直覺看結果,我違反反射原則來給得到的執行個體設定屬性友善列印資訊(後面講到相關類時會修改過來)。 package com.hlmtest.java.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class TestAccessibleObject { public static void main(String[] args ) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { //getConstructor(); getInstanceByConstructor (); } public static void getInstanceByConstructor() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ //先擷取Constructor對象 Class<TestClass> clzz = TestClass. class ; //先擷取無參的構造方法對象 @SuppressWarnings ( "rawtypes" ) Class[] str1 = null ; Constructor<TestClass> con1 = clzz .getConstructor( str1 ); //調用Constructor 的newInstance(Object... initargs ) 方法獲得主對象執行個體 TestClass obj1 = con1 .newInstance( str1 ) ; obj1 .setStr1( "我是obj1入參1" ); obj1 .setStr2( "我是obj1入參2" ); System. out .println( obj1 .toString()); //擷取有參的構造方法對象 @SuppressWarnings ( "rawtypes" ) Class[] str2 = {String. class ,String. class }; Constructor<TestClass> con2 = clzz .getConstructor( str2 ); //調用Constructor 的newInstance(Object... initargs ) 方法獲得主對象執行個體 TestClass obj2 = con2 .newInstance( "我是obj2入參1" , "我是obj2入參2" ); System. out .println( obj2 .toString()); } public static void getConstructor() throws NoSuchMethodException, SecurityException{ Class<TestClass> clzz = TestClass. class ; @SuppressWarnings ( "rawtypes" ) //構造方法數組 Constructor[] conList = clzz .getConstructors(); for (Constructor<?> r : conList ){ System. out .println( r .toGenericString()); } @SuppressWarnings ( "rawtypes" ) Class[] str = {String. class ,String. class }; //後者則傳回兩個及參對象的構造方法對象 Constructor<TestClass> con = clzz .getConstructor( str ); System. out .println( con .toGenericString()); @SuppressWarnings ( "rawtypes" ) Class[] str1 = {String. class ,String. class ,String. class }; //沒有入參為三個參數的構造方法,是以這裡會報 NoSuchMethodException 錯誤, //為了能列印我在這裡有預見性地把異常截住了 try { @SuppressWarnings ( "unused" ) Constructor<TestClass> con1 = clzz .getConstructor( str1 ); System. out .println( "沒有入參為三個參數的構造方法!" ); } catch (NoSuchMethodException e ){ System. out .println( e ); System. out .println( "沒有入參為三個參數的構造方法!" ); } } }
列印資訊為 str1:我是obj1入參1;str2我是obj1入參2 str1:我是obj2入參1;str2我是obj2入參2
以上便是通過反射的方式,利用構造方法的執行個體來得到反射類的執行個體對象。
Constructor 的更多API可以查詢: 中文網址:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh 英文網址:http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
20180528