反射是什么?
在運行狀態中,獲取一個類的所有屬性和方法。這種動態獲取信息以及調用對象的方法的功能。
使用反射機制的一些框架?
Retrofit中的注解功能、EventBus,動態生成框架 Gson。
使用反射技術查看類信息
獲取Class對象的三種方法
使用Object.getClass方法
如果我們能知道一個對象,可以通過調用這個對象的getClass方法獲得一個Class對象。
例如:
Person person = new Person();
Class<? extends Person> aClass = person.getClass();
System.out.println(aClass.getName());
這時候就會打印這個對象的全包名,aClass中還有其他信息。
使用.class方法
Class<? extends Person> aClass = Person.class;
System.out.println(aClass.getName());
System.out.println(int.class);
如果沒有獲取某個類的對象,無法使用getClass方法,可以直接在類名加上.class來獲取,這種方式可以用于基本數據類型。
使用Class.forName()方法
這個方法要使用一個類的完整路徑,就可以使用Class.forName("類的完整路徑")來得到相應的Class。
try {
Class mclass1 = Class.forName("main.fanshe.Person");
System.out.println(mclass1.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
注意:使用Class的newInstance()方法來創建對應類的實例,需要有默認的構造器,執行newInstance()方法實際上市利用默認構造器來創建該類的實例。
Class mclass1 = Class.forName("main.fanshe.Person");
Object o = mclass1.newInstance();
通過反射獲取成員變量
常用獲取成員屬性的方法
Field[] declaredFields = mclass1.getDeclaredFields();//獲取Class對象的所有屬性
Field[] fields = mclass1.getFields();//獲取class對象的public屬性
Field ageField = mclass1.getDeclaredField("age");//獲取class指定屬性
Field desFiedl = mclass1.getField("name");//獲取class指定的public屬性
如果獲取到屬性可以用過set方法進行修改例如:
Field ageField = mclass1.getDeclaredField("age");//獲取class指定屬性
ageField.setInt(o,22);
如果這個屬性是用private修飾的話,這樣寫的話代碼會報錯
java.lang.IllegalAccessException: Class main.fanshe.Main can not access a member of class main.fanshe.Person with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.setInt(Field.java:946)
at main.fanshe.Main.main(Main.java:50)
這時我們要添加 ageField.setAccessible(true);這個方法來聲明這個變量是可以訪問的就沒問題了,但是使用這個方法也可能會導致些其他問題,例如
在運行時雖然你通過反射修改了變量 a 的值,但其他部分可能還在使用原來的值。
通過反射獲取成員方法
Method[] methods = mclass1.getDeclaredMethods();//獲取class對象的所有聲明方法
Method[] allMethods = mclass1.getMethods();//獲取class對象的所有public聲明方法
Method method = mclass1.getMethod("getAge");//根據方法名返回方法
Method method2 = mclass1.getMethod("getAge",String.class);//根據帶指定形參列表的public方法
System.out.println(method.toString());
可以通過method.invoke(o);這個方法調用反射到的方法。
總結
反射還有好多其他方法,可以通過查詢API獲知,例如獲取構造方法等,功能貌似還是比較強大的,但是反射的一些操作可能會引起性能消耗,例如修改某個成員變量的時候,需要引發驗證訪問權限等額外操作等。所以使用反射的時候也許要考慮下性能方面的問題。
本篇文章參考:http://blog.csdn.net/u011240877/article/details/54604212