TIII-Android技術篇之反射
對於一個類來說,最重要的是什麼?
構造+屬性+方法+訪問許可權
待測試的類
/** * 作者:張風捷特烈 * 時間:2018/5/6:10:40 * 郵箱:[email protected] * 說明:反射測試類 */ public class Person { private int age; private String name; private boolean isMan; public String address="beijing"; public Person() { System.out.println("空參構造執行..."); } public Person( String name, int age,boolean isMan) { this.age = age; this.name = name; this.isMan = isMan; System.out.println("三參構造執行..."); } public void publicShow() { System.out.println("I am " + name + ",I " + age + "years"); } public static void staticShow() { System.out.println("staticShow"); } private void privateShow() { System.out.println("I am " + name + ",I " + age + "years"); } public void paramShow(String str,int num) { System.out.println("I am " + str + ",I " + num + "years"); } }
一、拿到Class物件
Class物件是什麼?
Class是一個類,而且它只有一個私有的建構函式,說明它不能通過new來獲取物件,建構函式傳入一個ClassLoader。 每個類被載入進入記憶體之後,系統就會為該類生成一個對應的java.lang.Class物件, 通過該Class物件就可以訪問到JVM中的這個類,就可以獲取某類的一切 private Class(ClassLoader loader) { // Initialize final field for classLoader.The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; }
1.物件.getClass()獲取Class物件
前提:已存在物件,未知該類全貌,可以使用此方法獲取Class物件來探測該類
Object類中有一個native方法獲取Class public final native Class<?> getClass();
public static void getClass_1() { Person person = new Person(); Class<? extends Person> personClass = person.getClass(); }
2.類名.class獲取Class物件
前提:需要已知類名
public static void getClass_2() { Class<Person> personClass = Person.class; }
3.通過指定字串:獲取Class物件
前提:需已知全類名
public static void getClass_3() { try { Class<?> person = Class.forName("top.toly.bean.Person"); System.out.println(person); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
二、通過反射構造物件
1.獲取無參構造例項化物件:clazz.newInstance()
/** * 通過反射建無參例項 */ public static void createInstance() { //早期:new 的時候,先根據類名尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 // 再建立該位元組碼檔案對相應的Person物件 try { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); Object instance = clazz.newInstance(); System.out.println(instance instanceof Person);//true } catch (Exception e) { e.printStackTrace(); }
2.通過反射建有參例項:clazz.getConstructor
/** * 通過反射建有參例項 */ private static void createInstance_2() { try { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); System.out.println(instance); //Person{age=24, name='捷特', isMan=true, address='beijing'} } catch (Exception e) { e.printStackTrace(); } }
補充:XXXDeclaredXXX都是隻獲取本類,不包括父類
// 獲得該類所有的構造器,不包括其父類的構造器 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) // 獲得該類所以public構造器,包括父類 public Constructor<T> getConstructor(Class<?>... parameterTypes)
三、通過反射獲取欄位
1.獲取公共欄位:clazz.getField
/** * 獲取公共欄位 */ public static void getPublicField() throws Exception { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); Field address = clazz.getField("address");//獲取公有欄位 Object o = address.get(clazz.newInstance()); System.out.println(o);//beijing }
2.獲取私有欄位:
/** * 獲取私有欄位 */ public static void getPrivateField() throws Exception { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); //可以獲取所有型別欄位 Field name = clazz.getDeclaredField("age"); //想要訪問私有,需要將可獲取置為true name.setAccessible(true); //設定私有成員值 name.setInt(instance,30); //獲取私有成員值 Object o = name.get(instance); System.out.println(o);//30 }
四、呼叫方法:
1.獲取公共方法:getMethods()
/** * 獲取公共方法 */ public static void getPublicMethod() throws Exception { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); //建立例項 Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); Method[] methods = clazz.getMethods();//只能獲取公有方法,包括父類 for (Method m : methods) { System.out.println(m); } //獲取公共無參 Method publicShow = clazz.getMethod("publicShow", null); //呼叫函式:invoke publicShow.invoke(instance, null); //獲取公共有參 Method paramShow = clazz.getMethod("paramShow", String.class, int.class); paramShow.invoke(instance, "龍少", 24); }
clazz.getDeclaredMethod:獲取指定名稱和引數型別的本類中宣告(訪問許可權不限)的方法
clazz.getDeclaredMethods(): 獲取該類所有的方法,不包括父類
clazz.getMethod:獲取當前類及所有繼承的父類的public修飾的方法。僅包括public
clazz.getMethods();獲取該類所有的public方法,包括父類的
2.獲取私有方法:getDeclaredMethods()
/** * 獲取私有方法 */ public static void getPrivateMethod() throws Exception { String className = "top.toly.bean.Person"; // 尋找到該類的位元組碼檔案,並載入到記憶體,建立該位元組碼檔案物件。 Class<?> clazz = Class.forName(className); Method[] declaredMethods = clazz.getDeclaredMethods();//獲取該類中的所有方法 //建立例項 Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class); Object instance = constructor.newInstance("捷特", 24, true); for (Method m : declaredMethods) { System.out.println(m); } Method privateShow = clazz.getDeclaredMethod("privateShow", null); privateShow.setAccessible(true); privateShow.invoke(instance,null); }
反射差不多也就這些,理論並不難,學以致用才是關鍵
後記、
1.宣告:
[1]本文由張風捷特烈原創,轉載請註明
[2]歡迎廣大程式設計愛好者共同交流
[3]個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
[4]你的喜歡與支援將是我最大的動力
2.連線傳送門:
ofollow,noindex">更多安卓技術歡迎訪問:安卓技術棧 我的github地址:歡迎star 簡書首發,騰訊雲+社群同步更新 張風捷特烈個人網站,程式設計筆記請訪問: http://www.toly1994.com
3.聯絡我
QQ:1981462002
微信:zdl1994328
4.歡迎關注我的微信公眾號,最新精彩文章,及時送達:

公眾號.jpg