您好,登錄后才能下訂單哦!
本篇內容主要講解“如何使用反射調用方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何使用反射調用方法”吧!
在一個類中除了有繼承的關系外,最為重要的操作就是類中的結構處理了,而類中的結構首先需要觀察的就是構造方法的使用問題,實際上在之前通過反射實例化對象的時候就已經接觸到構造方法的問題了:
實例化方法替代:clazz.getDeclaredConstructor().newInstance()
所有類的構造方法的獲取都可以直接通過Class類來完成,該類中定義有如下的幾個方法:
獲取所有構造方法:
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
獲取指定構造方法:
public Constructor<T> getConstructor() throws SecurityException
獲取所有構造方法:
public Constructor<?>[] getConstructors()throws SecurityException
獲取指定構造方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
范例:修改Person類的定義
AbstractBase:
public abstract class AbstractBase {public AbstractBase() {}public AbstractBase(String msg) {} }
Person:
public class Person extends AbstractBase implements IChannelService,IMessageService {public Person() {}public Person(String name, int age) { }
范例:獲取構造
JavaAPIDemo
public class JavaAPIDemo {public static void main(String[] args) { Class<?> cls = Person.class;//獲取指定類的Class對象Constructor<?>[] constructors = cls.getDeclaredConstructors(); //獲取全部構造for (Constructor<?> cons : constructors) { System.out.println(cons); } } }//執行結果:public cn.mldn.vo.Person()//public cn.mldn.vo.Person(java.lang.String,int)
此時獲取的是類中的全部構造方法,但是也可以獲取一個指定參數的構造。例如:現在的Person類之中有兩個構造方法:
修改Person:
public class Person extends AbstractBase implements IChannelService,IMessageService {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age; }public String getName() {return name; }public void setName(String name) {this.name = name; } @Overridepublic String toString() {return "姓名:" + this.name + "、年齡:" + this.age; } }
此時調用Person類中的有參構造方法進行Person類對象實例化,此時必須指明要調用的構造,而后通過Constructor類中提供的實例化方法操作:
public T newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
范例:調用指定構造實例化對象
import java.lang.reflect.Constructor;public class JavaAPIDemo {public static void main(String[] args) throws Exception { Class<?> cls = Person.class; Constructor<?> constructor = cls.getConstructor(String.class, int.class);Object obj = constructor.newInstance("小強", 78); System.out.println(obj); //姓名:小強、年齡:78} }
雖然程序代碼本身允許開發者調用有參構造,但是如果從實際的開發角度出發,所有使用反射的類中最好使用無參構造,因為這樣的實例化可以達到統一性。
在進行反射處理的時候也可以通過反射來獲取類之中的全部方法,但是需要提醒的是,如果想通過反射調用這些方法,必須有一個前提條件:類之中要提供實例化對象。
在Class類中提供了如下的操作可以獲取方法對象:
獲取全部方法:
public Method[] getMethods() throws SecurityException
獲取指定方法:
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
獲取本類全部方法:
public Method[] getDeclaredMethods() throws SecurityException
獲取本類指定方法:
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
范例:獲取全部方法
import java.lang.reflect.Method;public class JavaAPIDemo {public static void main(String[] args) throws Exception {Class<?> cls = Person.class; {Method methods [] = cls.getMethods();//獲取全部方法(包括父類中的方法)for (Method met : methods){System.out.println(met); } }System.out.println("---------------難以忘懷的愚人節的分割線-----------") { // 獲取本類方法Method methods [] = cls.getDeclaredMethods();for (Method met : methods){System.out.println(met); } } }
執行結果:
但是需要注意的是,這時的方法信息的獲取是依靠Method類提供的toString()方法完成的,很多時候也可以由用戶來拼湊方法信息的展示形式。
范例:自定義方法信息顯示
import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class JavaAPIDemo { public static void main(String[] args) throws Exception { Class<?> cls = Person.class; // 獲取指定類的Class對象Method methods[] = cls.getMethods(); for (Method met:methods){int mod=met.getModifiers();//修飾符System.out.print(Modifier.toString(mod)+">);System.out.print(met.getReturnType().getName()+" ");System.out.print(met.getName()+"("); Class<?> params [] = met.getParameterTypes();//獲取參數類型for (int x = 0; x < params.length; x ++) {System.out.print(params[x].getName() + " " + "arg-" + x);if(x < params.length - 1) {System.out.println(","); } }System.out.print(")");class<?> exp [] = met.getExceptionTypes();if(exp.length > 0) {System.out.print("throws"); } for(int x = 0 ; x < exp.length ; x ++) {System.out.print(exp[x].getName());if(x < exp.length - 1) {System.out.println(","); } }System.out.println(); //換行} } }
這種代碼只需要清楚可以根據反射獲取方法的結構即可,不需要過多深入了解,但在Method類中有一個致命的重要方法:
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
在Person類里面為name屬性追加有setter、getter方法。
public class Person extends AbstractBase implements IChannelService,IMessageService {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age; }public String getName() {return name; }public void setName(String name) {this.name = name; }// 其他操作代碼略}
需要通過反射機制來實現Person類之中的setter與getter方法的調用處理。
范例:在不導入指定類開發包的情況下實現屬性的配置
public class JavaAPIDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mladn.vo.Person"); //獲取指定類的Class對象// String attribute = "name"; //要操作的類屬性String value = "小強子"; //要設置的屬性內容//1.任何情況下如果要想保存類中的屬性或者調用類中的方法都必須保證存在有實例化對象,既然不允許導入包,那么就反射實例化Object obj = cls.getDeclaredConstructor().newInstance(); //調用無參構造實例化//2.如果要想進行方法的調用,那么一定要獲取方法的名稱String setMethodName = "setName"; //方法名稱 Method method = cls.getDeclaredMethodsetMethodName, String.class); //獲取指定的方法method.invoke(obj, value); //等價于:Person對象.setName(value);String getMethodName="getName";method=cls.getDeclaredMethod(getMethodName); //getter沒有參數System.out.println(getMethod.invoke(obj);); //等價于:Person對象.getName();} }
利用此類操作整體的形式上不會有任何明確的類對象產生,一切都是依靠反射機制處理的,這樣的處理避免了與某一個類耦合問題。
到此,相信大家對“如何使用反射調用方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。