跟我學Java反射——二步曲,跟我學java二步
上一篇文章我們已經將反射的基本知識和class類以及類的載入器進行了介紹,在上一篇我們還學習了四種得到Class類對象的方式,但是有了class對象我們能做些什麼呢,學習完這篇文章,就可以得到答案了.
擷取類的完整結構
這篇文章我們主要通過demo來學習,我先將demo需要用到的代碼進行簡單介紹.
一個介面MyInterface代碼:
package com.tgb.reflect.common;import java.io.Serializable;public interface MyInterface<T> extends Serializable {}
一個父類Creature,代碼是:
package com.tgb.reflect.common;public class Creature<T,N> {public double weight;public Creature(){}public void breath() {System.out.println("我是父類Creature的breath()方法");}}
一個註解類MyAnnotation,代碼是:
package com.tgb.reflect.common;import static java.lang.annotation.ElementType.CONSTRUCTOR;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.LOCAL_VARIABLE;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.ElementType.PARAMETER;import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {public String value();}
一個Person類,代碼是:
package com.tgb.reflect.common;/** * Person類繼承泛型Creature父類,實現兩個介面,本類含有不同許可權修飾符修飾的變數 * 含有不同許可權修飾符修飾、不同參數的建構函式;含有不同許可權修飾符修飾、不同參數的方法; * @author kang * */@MyAnnotation(value = "tgb")public class Person extends Creature<String,Object> implements Comparable<Integer>,MyInterface<String> {//不同許可權修飾符修飾的變數private int age;public String name;int id;//不同許可權修飾符修飾的擁有不同參數建構函式private Person(String name) {super();this.name = name;System.out.println("我是Person類的private修飾的帶參數建構函式Person(String name) ");}public Person() {super();System.out.println("我是Person類的public修飾的空參建構函式Person()");}Person(String name, int age) {super();this.name = name;this.age = age;System.out.println("我Person類的修飾符的帶參建構函式Person(String name, int age)");}@Overridepublic String toString() {System.out.println("我是Person類的public修飾的空參方法toString()");return "Person [name=" + name + ", age=" + age + "]";}@MyAnnotation(value = "abc123")public void show(){System.out.println("我是Person類的public修飾的帶註解的show()空參方法");}private void display(String nation){System.out.println("我是Person類的public修飾的帶註解的display()有參方法,參數是:"+nation);}public static void info(){System.out.println("我是Person類的public修飾的info()空參靜態方法");}class Bird{}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int compareTo(Integer o) {return 0;}}
擷取運行類建構函式
我們可以用得到的Class對象,通過反射來擷取該Class對象的所有建構函式,
擷取運行類許可權修飾符為public的建構函式
//擷取運行類許可權修飾符為public的建構函式@Testpublic void test2(){String className = "com.tgb.reflect.common.Person";Class class1 = Class.forName(className);
<span style="white-space:pre"></span>Constructor[] conClasses=clazz.getConstructors();for (int i = 0; i < conClasses.length; i++) {System.out.println(conClasses[i]);}}
運行結果為:
public com.tgb.reflect.common.Person()
擷取運行類所有的建構函式
//擷取運行類所有的建構函式@Testpublic void test2() throws ClassNotFoundException{String className = "com.tgb.reflect.common.Person";Class clazz = Class.forName(className);Constructor[] conClasses=clazz.getDeclaredConstructors();for (int i = 0; i < conClasses.length; i++) {System.out.println(conClasses[i]);}}
運行結果:
com.tgb.reflect.common.Person(java.lang.String,int)
publiccom.tgb.reflect.common.Person()
privatecom.tgb.reflect.common.Person(java.lang.String)
由此我們得出結論,getConstructors()可以獲得運行類的public的建構函式,getDeclaredConstructors()可以獲得運行類的所有建構函式。
擷取運行類對象執行個體
我們可以用得到的Class對象,來建立類的對象執行個體,在建立對象執行個體時,要就用到了我們剛才上面講到的建構函式,不同的建構函式,建立對象執行個體的方法也是不一樣的.
空參構造器
//利用運行類的空參建構函式,來建立運行類對象的執行個體@Testpublic void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{String className = "com.tgb.reflect.common.Person";Class class1 = Class.forName(className);//擷取運行類的空參建構函式Constructor constructor = class1.getConstructor();//建立對應的運行類對象時,使用newInstance,實際上就是調用了運行時類的空參的構造器;Person person = (Person)constructor.newInstance();System.out.println(person);}
運行結果:
我是Person類的public修飾的空參建構函式Person()
我是Person類的public修飾的空參方法toString()
Person [name=null,age=0]
非空參構造器
// 利用運行類的非空參建構函式,建立運行類的執行個體對象@Testpublic void test4() throws ClassNotFoundException, NoSuchMethodException,SecurityException, InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException {String className = "com.tgb.reflect.common.Person";Class class1 = Class.forName(className);// 擷取運行類的帶參數的建構函式Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);constructor.setAccessible(true);// 利用構造器建立運行類的執行個體對象Person p = (Person) constructor.newInstance("luowei", 20);System.out.println(p);}
運行結果:
我Person類的修飾符的帶參建構函式Person(Stringname, int age)
我是Person類的public修飾的空參方法toString()
Person [name=luowei,age=20]
通過上面兩種方法,我們可以學習到的利用空參和非空參構造器來建立運行類的執行個體對象
有了Class類對象除了可以通過建構函式擷取運行類執行個體,還可以擷取運行類的其它一些內容.
擷取運行類父類
1.擷取運行類的父類
// 1.擷取運行類的父類@Testpublic void test1() {Class class1 = Person.class;Class parentClass = class1.getSuperclass();System.out.println(parentClass);}
運行結果:
classcom.tgb.reflect.common.Creature
2.擷取運行類的帶著泛型的父類
由於我們的父類是帶著泛型的,通過上面這種擷取到的父類並沒有帶泛型,所有我們可以通過以下方法來擷取運行類的帶著泛型的父類.
// 2.擷取運行類的帶著泛型的父類@Testpublic void test2() {// 得到運行類本身Class class1 = Person.class;// 得到運行類的帶泛型的父類Type type = class1.getGenericSuperclass();System.out.println(type);}
運行結果:
com.tgb.reflect.common.Creature<java.lang.String,java.lang.Object>
3.擷取運行類的父類的泛型
我們已經得到帶著泛型的父類了,現在我們要得到父類的泛型,我們可以用接下來的方法.
// 3.擷取運行類的父類的泛型@Testpublic void test3() throws ClassNotFoundException{//通過類載入器得到運行類本身String className= "com.tgb.reflect.common.Person";ClassLoader classLoader =this.getClass().getClassLoader();Class class1=classLoader.loadClass(className);//得到運行類的帶泛型的父類Type type = class1.getGenericSuperclass();ParameterizedType param = (ParameterizedType) type;Type[] types= param.getActualTypeArguments();for (int i = 0; i < types.length; i++) {System.out.println(((Class)types[i]).getName());}}
運行結果:
java.lang.String
java.lang.Object
擷取運行類實現的介面
1.擷取運行類實現的所有介面
//1.擷取運行類實現的介面@Testpublic void test1() throws ClassNotFoundException{//通過類載入器得到運行類本身String className= "com.tgb.reflect.common.Person";ClassLoader classLoader =this.getClass().getClassLoader();Class class1=classLoader.loadClass(className);//擷取運行類實現的介面Class[] interfaces=class1.getInterfaces();for (int i = 0; i < interfaces.length; i++) {System.out.println(interfaces[i]);}}
運行結果:
interfacejava.lang.Comparable
interfacecom.tgb.reflect.common.MyInterface
2.擷取運行類的帶著泛型的介面
//2.擷取運行類實現的帶泛型的介面@Testpublic void test2() throws ClassNotFoundException{//通過類載入器得到運行類本身String className= "com.tgb.reflect.common.Person";ClassLoader classLoader =this.getClass().getClassLoader();Class class1=classLoader.loadClass(className);//擷取運行類實現的介面Type[] types=class1.getGenericInterfaces();for (int i = 0; i < types.length; i++) {System.out.println(types[i]);}}
運行結果:
java.lang.Comparable<java.lang.Integer>
com.tgb.reflect.common.MyInterface<java.lang.String>
3.擷取運行類的介面的泛型
//3.擷取運行類實現的帶泛型的介面@Testpublic void test3() throws ClassNotFoundException{//通過類載入器得到運行類本身String className= "com.tgb.reflect.common.Person";ClassLoader classLoader =this.getClass().getClassLoader();Class class1=classLoader.loadClass(className);//擷取運行類實現的介面Type[] types=class1.getGenericInterfaces();for (int i = 0; i < types.length; i++) {//擷取每一個介面的泛型參數類型ParameterizedType params = (ParameterizedType) types[i];Type[] para= params.getActualTypeArguments();for (int j = 0; j < para.length; j++) {System.out.println(((Class)para[j]).getName());}}
運行結果:
java.lang.Integer
java.lang.String
通過上面的介紹我們可以擷取到運行類介面、泛型介面和泛型的具體類型。
擷取運行類的所在的包
//1.擷取運行類的所在的包@Testpublic void test6(){//通過運行類本身來得到運行類Class class1 = Person.class;Package packageClass = class1.getPackage();System.out.println(packageClass.getName());}
運行結果:
com.tgb.reflect.common
擷取運行類的註解
//擷取運行類的註解@Testpublic void test7(){//通過運行類本身來得到運行類Class class1 = Person.class;//得到運行類的註解Annotation[] annotations=class1.getAnnotations();for (int i = 0; i < annotations.length; i++) {System.out.println(annotations[i]);}}
運行結果:
@com.tgb.reflect.common.MyAnnotation(value=tgb)
後記
這篇文章我們通過具體代碼學習了,如何在得到運行類的Class對象後通過反射得到運行類的空參和有參的建構函式,並通過這些建構函式產生運行類的執行個體對象,同時還可以得到運行類的父類和介面,以及包括泛型父類、泛型介面、父類或者介面具體的泛型。下篇文章我們繼續反射的學習。