java(19)---反射機制
java---反射機制
java語言允許通過程式化的方式間接對Class進行操作,Class檔案由類載入器裝載後,在JVM中形成一份描述Class結構的元資訊物件,通過該元資訊物件可以獲知Class的結構資訊:如
建構函式、屬性和方法等。
java允許使用者藉由這個Class相關的元資訊對物件間接呼叫Class物件的功能。
11.1、什麼是反射?
反射機制是在執行狀態中:
對於任意的一個類,都能夠知道這個類的所有屬性和方法
對於任意的一個物件,都能夠呼叫它的任意一個方法和屬性。
11.2、反射提供的功能有:
1)、在執行時判斷任意一個所屬的類
2)、在執行時構造任意一個類的物件
3)、在執行時判斷任意一個類所具有的成員變數和方法
4)、在執行時呼叫任意一個物件的方法
5)、生成動態代理
11.3、獲取反射物件的三種方式
第一種、Class.forName(全類名),推薦使用,可以捕獲異常ClassNotFoundException
package com.cn.fanshe; public class Test { public static void main(String[] args) { //獲取反射物件(反射入口):: /** * 獲取反射物件有 * 第一種、Class.forName(全類名) * 第二種、類名.class * 第三種、物件.getClass() * */ try { Class<?> userClazz=Class.forName("com.cn.fanshe.User"); System.out.println(userClazz); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } |
第二種、類名.class
Class<?> userClazz=User.class; System.out.println(userClazz); |
第三種、物件.getClass()
//1.建立物件 User user=new User(); Class<?> userClazz=user.getClass(); System.out.println(userClazz); |
11.4、獲取反射類中的所有公共方法
package com.cn.fanshe; import java.lang.reflect.Method; /** * 1、獲得所有的公共方法(本類、父類以及介面中的所有方法,符合訪問修飾符的public方法,但不包括private方法) * */ public class Test { public static void getAllMethod(){ //1.獲得反射物件 Class<?> userClazz=null; try { userClazz=Class.forName("com.cn.fanshe.User"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //2.獲得所有的公共方法 Method[] methods=userClazz.getMethods(); //3.遍歷所有的公共方法 for(Method method:methods){ System.out.println(method); } } public static void main(String[] args) { Test.getAllMethod(); } } |
11.5、獲得反射類中的所有介面
//1.獲得反射物件 Class<?> userClazz=null; try { userClazz=Class.forName("com.cn.fanshe.User"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Class<?>[] userInterfaces=userClazz.getInterfaces(); for(Class<?> inter:userInterfaces){ System.out.println(inter); } |
11.6、獲得所有的父類,父類只有1個
Class<?> superClass=userClazz.getSuperclass(); System.out.println(superClass); |
11.7、獲得所有的構造方法
Constructor<?>[] constructors=userClazz.getConstructors(); for(Constructor<?> con:constructors){ System.out.println(con); } |
11.8、獲取所有的公共屬性
Field[] fields=userClazz.getFields(); for(Field fie:fields){ System.out.println(fie); } |
注:獲取所有公共屬性和方法,則修改為如下:
Field[] fields=userClazz.getDeclaredFields(); |
11.9、獲取物件的例項,並操作物件
package com.cn.fanshe; import java.lang.reflect.Field; /** * 1、獲得所有的公共方法(本類、父類以及介面中的所有方法,符合訪問修飾符的public方法,但不包括private方法) * */ public class Test { public static void test() throws InstantiationException, IllegalAccessException{ //1.獲得反射物件 Class<?> userClazz=null; try { userClazz=Class.forName("com.cn.fanshe.User"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //2.獲取物件例項 User user=(User) userClazz.newInstance(); user.setName("Jerry"); user.setAge(21); System.out.println(user.getName()+","+user.getAge()); } public static void main(String[] args) throws InstantiationException, IllegalAccessException { Test.test(); } } |
11.10、建立物件例項並操作物件屬性
//1.獲得反射物件 Class<?> userClazz=null; try { userClazz=Class.forName("com.cn.fanshe.User"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //2.獲取物件例項 User user=(User) userClazz.newInstance(); Field nameField=userClazz.getDeclaredField("name"); nameField.set(user, "張三"); System.out.println(user.getName()); |
此時會報異常,如下:
Exception in thread "main" java.lang.IllegalAccessException: Class com.cn.fanshe.Test can not access a member of class com.cn.fanshe.User with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253) at java.lang.reflect.Field.doSecurityCheck(Field.java:983) at java.lang.reflect.Field.getFieldAccessor(Field.java:927) at java.lang.reflect.Field.set(Field.java:680) at com.cn.fanshe.Test.test(Test.java:19) at com.cn.fanshe.Test.main(Test.java:24) |
原因是訪問的是私有的name,需要修改屬性的訪問許可權,如果因為訪問修飾符限制造成的異常,可以通過屬性或方法.setAccessible(true),暫時性的開啟許可權。
如下:
//2.獲取物件例項 User user=(User) userClazz.newInstance(); Field nameField=userClazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(user, "張三"); System.out.println(user.getName()); |
注:方法的操作類似屬性,但是方法的呼叫用invoke()
如下:
//2.獲取物件例項 User user=(User) userClazz.newInstance(); //interfaceMethod2是方法名,null是引數型別 Method method=userClazz.getDeclaredMethod("interfaceMethod2", null); method.invoke(user, null); //常規方法呼叫如user.say(引數) |
11.11、反射的適用場景?
1)、java的反射機制在做基礎框架時十分有用,即反射機制是很多java框架的基石。
最經典的就是在XML檔案或Properties裡面寫好配置,然後在java類裡面解析XML或properties裡面的內容,得到一個字串,然後用反射機制,根據這個字串獲得某個類的Class例項,這樣就可以動態配置一些東西,不用每次都要在程式碼裡面去new或者做其它事情,以後要改的話直接修改配置檔案,程式碼維護起來就方便了。
2)、java類裡面不一定能直接呼叫另外的方法,這時可以通過反射機制來實現。
3)、在編碼階段不知道那個類名,要在執行期從配置檔案讀取類名,這時就沒辦法硬編碼new ClassName();而必須用到反射才能建立這個物件,反射的目的就是為了擴充套件未知的應用。
11.12、反射的效能問題
反射機制是一種程式自我分析的能力,用於獲取一個類的變數、建構函式、方法、修飾符
優點:執行期型別的判斷,動態類載入,動態代理使用反射
缺點:效能是一個問題,反射相當於一系列解釋操作,通知JVM要做的事情,效能比直接的java程式碼要慢很多。
11.13、程式設計師在自己的業務開發中應該儘量遠離反射
反射:在流行的庫如hibernate和spring中,反射自然有其用武之地。不過內省業務程式碼在很多時候都不是一件好事,原因有很多,總之不建議使用反射。
首先是程式碼可讀性和工具支援,開啟IDE,尋找你的java程式碼的內部依賴,很容易吧。
現在使用反射來替換掉你的程式碼然後再試一下,結果如何呢?如果通過反射來修改已經封裝好的物件狀態,那麼結果將會變得更加不可控。
相關推薦
java(19)---反射機制
java---反射機制 java語言允許通過程式化的方式間接對Class進行操作,Class檔案由類載入器裝載後,在JVM中形成一份描述Class結構的元資訊物件,通過該元資訊物件可以獲知Class的結構資訊:如 建構函式、屬性和方法等。 java允許使用者藉由這個Cl
Java--(二)反射之在執行時使用反射分析物件
對於我這樣一個菜鳥級別的人來說,學習反射真心有點鬱悶,今天繼續分享一下學習心得。在執行時反射分析物件,可以利用反射機制,檢視資料域的實際內容,檢視物件域的關鍵方法是Field類中的get方法,例如f是一個Field型別的物件,(通過getDeclarerFields得到的物件
小白也能看懂的外掛化DroidPlugin原理(二)-- 反射機制和Hook入門
前言:在上一篇博文《小白也能看懂的外掛化DroidPlugin原理(一)-- 動態代理》中詳細介紹了 DroidPlugin 原理中涉及到的動態代理模式,看完上篇博文後你就會發現原來動態代理真的非常簡單,只不過就是實現一個 InvocationHandler 介面重寫一
Java程式設計師從笨鳥到菜鳥之(八)反射和代理機制
反射和代理機制是JDK5.0提供的java新特性,反射的出現打破了java一些常規的規則,如,私有變數不可訪問。但反射和代理在學習過程中也是一個比較難理解的知識點。本人曾經學過一段時間的反射和代理,但好長時間不用好像有點生疏了,當時學的時候就理解的不是很透徹,這次總結算是重新學習一遍吧,如果有什麼錯誤,
Java基礎(十三)反射
構造 調用 div for 性能 使用 判斷 true con 一、反射 1、反射概念 JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱
8.2(java學習筆記)反射
一、基礎知識 物件是表示或封裝一些資料,一個類被載入後JVM會建立一個對應該類的Class物件, 類的整個結構資訊會被放在對應的物件中,通過這個物件我們可以獲取改類的全部資訊, 而這些操作稱為反射。 二、反射基本操作 2.1獲取物件類 上面說了每一個類在載入時會
java 反射(四) 反射對屬性、方法的操作
package com.reflect; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 反
java 反射(二) 反射中Class常見的方法和屬性
package com.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 反射中Class常見的方法和屬
Java高階篇(四)——反射
之前寫到了設計模式的代理模式,因為下一篇動態代理等內容需要用到反射的知識,所以在之前Java篇的基礎上再寫一篇有關反射的內容,還是以實際的程式為主,瞭解反射是做什麼的、應該怎麼用。 一、什麼是反射 反射就是把Java類中的各個成分對映成一個個的Java物件。即在執行狀態中,對於任意一個類,都能夠知道這
Java提高班(六)反射和動態代理(JDK Proxy和Cglib)
反射和動態代理放有一定的相關性,但單純的說動態代理是由反射機制實現的,其實是不夠全面不準確的,動態代理是一種功能行為,而它的實現方法有很多。要怎麼理解以上這句話,請看下文。 一、反射 反射機制是 Java 語言提供的一種基礎功能,賦予程式在執行時自省(introspect,官方用語)的能力。通過反射我們可
Java內容梳理(19)API學習(7)執行緒
目錄: 1、程序和執行緒 2、執行緒的建立 3、執行緒的執行方式和使用場景 4、執行緒的生命週期 5、執行緒優先順序 6、守護執行緒 7、執行緒常用API 8、執行緒安全 9、鎖機制 10、執行緒同步控制(死鎖的介紹) 11、定時器 1、程序和執行
Netflix Eureka原始碼分析(19)——eureka server叢集機制原始碼剖析:登錄檔同步以及高可用
(1)eureka core的BootStrap裡面,有一塊程式碼,是PeerEurekaNodes的程式碼,其實是在處理eureka server叢集資訊的初始化,會執行PeerEurekaNodes.start()方法 public class EurekaBootSt
JAVA基礎(19)---陣列的定義、初始化及遍歷
陣列 陣列的定義:將同種型別的資料,有組織的存放與一定的記憶體空間中。 陣列的定義格式: 常用的格式: ①資料型別[] 陣列名稱 = new 資料型別[定義陣列的大小];
HDPCD-Java-複習筆記(19)
Hive Apache Hive maintains metadata information in a metastore to generate tables. A Hive table consists of: · A schema stor
Java集合——HashMap(四)擴容機制——resize()
HashMap的擴容機制---resize() 雖然在hashmap的原理裡面有這段,但是這個單獨拿出來講rehash或者resize()也是極好的。 什麼時候擴容:當向容器新增元素的時候,會判斷當前容器的元素個數,如果大於等於閾值(知道這個閾字怎麼念嗎?不念fa值
Java基礎(三)反射和Class
一、簡介 Java反射是Java被視為動態語言的一個關鍵性質,這個機制允許程式在執行時透過Reflection APIs取得任何一個已知名稱的class的內部資訊,包括其modifiers(諸如public, static 等)、superclass(例如Object)、實現之interface
java併發——執行緒池(一)執行機制和如何使用
合理利用執行緒池能夠帶來三個好處。 1、第一:降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 2、第二:提高響應速度。當任務到達時,任務可以不需要的等到執行緒建立就能立即執行。 3、第三:提高執行緒的可管理性。執
Haskell語言學習筆記(19)File IO
副作用 才會 lose file 類型 ask pen 函數 有效 關於IO Action 類型為IO t。 運算時不執行,因而沒有任何效果,只有執行時才會有效果,產生副作用。 一個IO Action只有在其他IO Action中才能被執行。 類型為IO t的I
ActiveMQ(19):Consumer高級特性之獨有消費者(Exclusive Consumer)
consumer高級特性之獨有消費者(exclusive consumer)一、簡介Queue中的消息是按照順序被分發到consumers的。然而,當你有多個consumers同時從相同的queue中提取消息時,你將失去這個保證。因為這些消息是被多個線程並發的處理。有的時候,保證消息按照順序處理是很重要的。如
Windows Phone開發(19):三維透視效果
end 理論知識 form 之間 3d模型 中間 第一個 一個 好的 三維效果也可以叫透視效果,所以,我幹脆叫三維透視效果。理論知識少講,直接用例開場吧,因為這個三維效果其實很簡單,比上一節中的變換更省事,不信?一起來做一做練習吧。 練習一:把對象沿Y軸旋轉45度。 默認情