java的反射到底是有什麼用處?怎麼用?

沈依依


Java的反射機制是Java特性之一,反射機制是構建框架技術的基礎所在。靈活掌握Java反射機制,對大家以後學習框架技術有很大的幫助。

什麼是Java的反射?

反射是Java的特徵之一,是一種間接操作目標對象的機制。

JAVA反射機制是在運行狀態中,對於任意一個實體類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。

Java反射有什麼作用?

通過反射可以使程序代碼訪問裝載到JVM 中的類的內部信息

● 獲取已裝載類的成員變量信息

● 獲取已裝載類的方法

● 獲取已裝載類的構造方法信息

反射的應用場合:

在編譯時根本無法知道該對象或類可能屬於哪些類,程序只依靠運行時信息來發現該對象和類的真實信息。

反射的缺點

性能問題

使用反射基本上是一種解釋操作,用於字段和方法接入時要遠慢於直接代碼。因此Java反射機制主要應用在對靈活性和擴展性要求很高的系統框架上,普通程序不建議使用。

使用反射會模糊程序內部邏輯

程序人員希望在源代碼中看到程序的邏輯,反射等繞過了源代碼的技術,因而會帶來維護問題。反射代碼比相應的直接代碼更復雜


經典老車俱樂部


一個非常好的問題。我是工作多年的Web應用架構師,來回答一下這個問題。歡迎關注我,瞭解更多IT專業知識。


一,定義

Java反射機制是在運行狀態中,對於任意一個類,都能夠知道它的屬性和方法;對於任意一個對象,都能夠調用它的屬性和方法。這種動態獲取信息以及動態調用對象方法的功能被稱為Java語言的反射機制。


二,用途

在Java程序運行過程中,獲取任意需要的類和對象的信息。


三,舉例:通過反射在運行時讀取註解信息

Java中,Package、Class、Constructor、Method、Field都實現了一個接口AnnotatedElement,聲明在java.lang.reflect反射包中,有如下方法:


四,代碼實現

@Retention(RetentionPolicy.RUNTIME)
public @interface HelloAnnotation {
String value() default "Hello Annotation!";
}

2,引用註解

@HelloAnnotation("Hello Bean!")
public class HelloBean {
}

3,運行時調用反射獲取註解

public class HelloClassTest {
@Test
public void testClass() throws NoSuchMethodException {
Class> clazz = HelloClass.class;
HelloAnnotation annotation = clazz.getAnnotation(HelloAnnotation.class);
System.out.println(String.format("類: %s, 註解: %s, 值:%s\

急速馬力快de源碼客


  • 反射所需的類在java.lang.reflect包下提供。
  • 反射為我們提供了有關對象所屬類的信息,以及可以使用該對象執行的該類的方法。
  • 通過反射,我們可以在運行時調用方法,而與它們所使用的訪問說明符無關。

反射可用於獲取有關一些的有用信息

  1. getClass()方法用於獲取對象所屬的類的名稱。
  2. 構造函數 getConstructors()方法用於獲取對象所屬類的公共構造函數。
  3. 方法 getMethods()方法用於獲取對象所屬類的公共方法。

簡單的例子

為了先清楚下反射的用處,我們將看一個非常基本的示例,該示例在運行時檢查簡單Java對象的字段。

讓我們創建一個簡單的Person類,其中僅包含name和age字段,而根本不包含任何方法。這是Person類:

現在,我們將使用Java反射來發現此類所有字段的名稱。為了欣賞反射的力量,我們將構造一個Person對象並將Object作為引用類型:

這個測試告訴我們,我們能夠得到的數組Field對象從我們人的對象,即使參考對象是對象的父類。

在上面的示例中,我們僅對這些字段的名稱感興趣,但是還有很多事情可以做,我們將在後續部分中看到更多示例。

注意我們如何使用一個輔助方法來提取實際的字段名,這是一個非常基本的代碼:

重點觀察

  1. 如果知道方法的名稱和參數類型,則可以通過反射調用該方法。為此,我們使用以下兩種方法getDeclaredMethod():創建要調用的方法的對象。該方法的語法是Class.getDeclaredMethod(名稱,參數類型)name-要創建其對象的方法的名稱parametertype-參數是Class對象的數組

    invoke():要在運行時調用類的方法,我們使用以下方法——

    Method.invoke(對象,參數)如果類的方法不接受任何方法 參數,然後將null用作參數。
  2. 通過反射,我們可以在類的類對象的幫助下訪問類的私有變量和方法,並通過使用對象來調用方法,如上所述。為此,我們使用以下兩種方法。

    Class.getDeclaredField(FieldName):用於獲取私有字段。返回指定類型字段名稱的字段類型的對象。Field.setAccessible(true): 允許訪問該字段,而與該字段使用的訪問修飾符無關。

使用發射的優勢

    • 可擴展性功能:應用程序可以通過使用其完全限定的名稱創建可擴展性對象的實例來使用外部的用戶定義類。
    • 調試和測試工具:調試器使用反射的屬性檢查類的私有成員。

    缺點

      • 性能開銷:反射操作比非反射操作的性能要慢,因此應避免在對性能敏感的應用程序中經常調用的代碼段中避免這樣做。
      • 內部曝光:反射代碼破壞了抽象,因此可能會隨著平臺升級而改變行為。

      大魔王Hacker




      反射的功能


      1. 在運行時判斷任意一個對象所屬的類

      2. 在運行時構造任意一個類的對象

      3. 在運行時判斷任意一個類所具有的成員變量和方法

      4. 在運行時調用任意一個對象的方法

      Class類

      1. 獲得類相關的方法

      getClassLoader():獲得類的加載器

      forName(String className):根據類名返回類的對象

      getName():獲得類的完整路徑名字

      newInstance():創建類的實例

      getPackage():獲得類的包

      getSimpleName():獲得類的名字

      getInterfaces():獲得當前類實現的類或是接口

      getSuperclass():獲得當前類繼承的父類的名字


      2. 獲得類中屬性相關的方法


      getField(String name): 獲得某個公有的屬性對象

      getFields(): 獲得所有公有的屬性對象

      getDeclaredField(String name):獲得某個屬性對象

      getDeclaredFields():獲得所有屬性對象


      注意: getFields() 和 getDeclaredFields() 的區別??


      3.獲得類中註解相關的方法

      getAnnotation(Class

      getAnnotations(): 返回該類所有的公有註解對象

      getDeclaredAnnotation(Class

      getDeclaredAnnotations(): 返回該類所有的註解對象


      4. 獲得類中構造器相關的方法


      getConstructor(Class...> parameterTypes):獲得該類中與參數類型匹配的公有構造方法


      getConstructors():獲得該類的所有公有構造方法


      getDeclaredConstructor(Class...> parameterTypes):獲得該類中與參數類型匹配的構造方法

      getDeclaredConstructors(): 獲得該類所有構造方法


      5.獲得類中方法相關的方法

      getMethod(String name, Class...> parameterTypes): 獲得該類某個公有的方法

      getMethods(): 獲得該類所有公有的方法

      getDeclaredMethod(String name, Class...> parameterTypes):獲得該類某個方法

      getDeclaredMethods():獲得該類所有方法


      Field類 -代表類的成員變量,


      equals(Object obj): 屬性與obj相等則返回true

      get(Object obj):獲得obj中對應的屬性值

      set(Object obj, Object value):設置obj中對應屬性值


      Method類


      invoke(Object obj,Object args[]): 傳遞object對象及參數調用該對象對應的方法


      Constructor類


      newInstance(Object... initargs): 根據傳遞的參數創建類的對象


      獲取對應類的Class對象


      1. Class.forName("java.lang.String")

      2. 使用類的.class語法: String.class

      3. 使用對象的getClass()方法,String s = "aa";Class> clazz = s.getClass();


      通過類的不帶參數的構造方法生成對象


      1. 先獲取Class對象,然後通過該Class對象的newInstance()方法直接生成即可


      Class> classType = String.class;

      Object obj = classType.newInstance();


      2.先獲取Class對象,然後通過該對象獲得對應的Constructor對象,再通過該Constructor對象的newInstace()方法生成


      Class> classType = String.class;

      Constructor cons = classType.getConstructor(new Class[]{});

      Object obj = cons.newInstance(new Object[]{})



      3.通過帶參數的構造方法


      Class> classType = String.class;

      Constructor cons = classType.getConstructor(new Class[]{String.class,int.class});

      Object obj = cons.newInstance(new Object[]{"hello\

      碼農的一天


      Java的反射機制簡單來說就是程序運行的時候能夠獲取自身的信息。只要給定類的名字,就可以通過反射機制來獲得類的所有信息。

      比如說Class.forName("com.mysql.jdbc.Driver.class").newlnstance();生成驅動對象實列。這個就是反射。

      比如說編寫訪問數據庫時有了Java反射機制,只需要寫一個dao類,四個方法,增刪改查,傳入不同的對象,就可以了。而不用每一個表都創建一個dao類,反射機制會自動完成剩下的事情。專門做那些重複的有規則的事情。

      比如說用反射機制實現對數據庫數據的增查。

      先定規則,數據庫的每一個表對象一個pojo類,表中的每一個字段對應pojo類中的一個屬性,類的名字和表的名字相同。

      為pojo類的每一個屬性添加標準的set和get方法。

      然後就可以書寫代碼了,由於反射的靈活性很高,我們沒有必要把精力放在操作代碼,方法更多時間放在邏輯功能上。可以減少開發時間,代碼可讀性好。


      果蔬烘乾機


      本人10年開發培訓經驗,期間經歷了Java Web,Android,H5,大數據,PHP等多個不同的方向的開發,也做過軟件培訓公司的金牌講師,很有興趣回答你這個問題。

      反射技術,可以說是java開發裡的一大利器,很多的orm框架,ioc框架,源碼內部都會用到反射技術。尤其是反射加註解,兩者結合,可以做很多工作。反射一般是作用在運行時階段,通過拿到字節碼,進行反向操作。我們可以通過java的反射技術,動態的拿到我們想要的類中的很多信息。


      我從事互聯網開發10年,主要的研究方向集中在Java web微服務架構領域,Android移動端研發,HTML5前端方向,我會陸續寫一些關於互聯網技術方面的文章,感興趣的朋友可以關注我,相信你一定會有所收穫。

      如果有Java,Android,H5等開發方面的問題,或者是開發求職方面的問題,都可以在評論區留言,或者私信我。


      一一哥Sun


      Java反射說的是在運行狀態中,對於任何一個類,我們都能夠知道這個類有哪些方法和屬性。對於任何一個對象,我們都能夠對它的方法和屬性進行調用。我們把這種動態獲取對象信息和調用對象方法的功能稱之為反射機制。

      可以不通過new關鍵字獲取對象並且使用類對象中的成員變量,方法,修飾符等等,在這裡舉例獲取類。

      第一種:使用Class.forName(String classPath) ClassPath:寫需要反射的類名,一般是以包名.類名。如:Class clazz = Class.forName("com.entity.Example");

      第二種:直接使用Class clz = 類名.class

      這種情況一般在我們知道有這個類的時候去使用。如:Class clz = Example.class;

      第三種:Class clz = 對象. getClass();

      前提是對象已經被實例化出來了 。如:

      Example ex = new Example();

      Class clz = ex.getClass();

      這三種方法都有各自的優點,一般我們使用第一種比較多,按照自己的實際需求去使用才是最好的。反射有啥用?有啥應用場景?

      1.spring框架的ioc是基於java的反射機制。

      2.JDBC 的數據庫的連接註冊驅動,獲取連接也是基於Java反射。

      3.Hibernate,Mybatis都有運用到反射。



      代碼接盤俠


      簡單的來說,反射機制其實就是指程序在運行的時候能夠獲取自身的信息。如果知道一個類的名稱或者它的一個實例對象, 就能把這個類的所有方法和變量的信息(方法名,變量名,方法,修飾符,類型,方法參數等等所有信息)找出來。如果明確知道這個類裡的某個方法名+參數個數 類型,還能通過傳遞參數來運行那個類裡的那個方法,這就是反射。

      在Java中,Class類與java.lang.reflect類庫一起對反射的概念提供了支持,該類庫包含了Field、Method以及Constructor類(每個類都實現了Member接口)。我們知道對RTTI(運行時類型識別)來說,編譯器在編譯時打開和檢查.class文件。而對於反射機制來說,.class文件在編譯時是不可獲取的,所以是在運行時打開和檢查.class文件的。

      這個是比較簡單的說法,真正解釋起來幾篇文章也說不完,聯繫題主搜下相關技術博客,相關介紹還是很多的。



      通信人的自我修養


      反射不需要你主動去new對象,直接根據類全名就可以實例化對象,這在寫各種框架上面很方便,比如一開始的spring 配置文件模式就是直接在配置文件裡指定類全名即可


      分享到:


相關文章: