日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何有效地使用反射

發布時間:2023/12/3 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何有效地使用反射 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是我們名為“ 高級Java ”的學院課程的一部分。

本課程旨在幫助您最有效地使用Java。 它討論了高級主題,包括對象創建,并發,序列化,反射等。 它將指導您完成Java掌握的過程! 在這里查看 !

目錄

1.簡介 2.反射API 3.訪問泛型類型參數 4.反射API和可見性 5.反射API陷阱 6.方法句柄 7.方法參數名稱 8.接下來 9.下載源代碼

1.簡介

在本教程的這一部分中,我們將簡要介紹一個非常有趣的主題,即反射反射是程序在運行時檢查或自檢的能力。 反射是一項極其有用且功能強大的功能,它可以極大地擴展程序的功能,以在執行過程中執行其自身的檢查,修改或轉換,而無需一行代碼更改。 并非所有的編程語言實現都支持此功能,但是幸運的是Java自一開始就采用了此功能。

2.反射API

反射API是Java標準庫的一部分,它提供了一種在運行時探索內在類詳細信息,動態創建新類實例(無需顯式使用new運算符),動態調用方法,自省注釋(已添加注釋)的方法。在教程的第5部分“ 如何以及何時使用Enums和Annotations”中進行了介紹 ,以及更多其他內容。 它使Java開發人員可以自由編寫代碼,這些代碼可以在運行時自行調整,驗證,執行甚至修改自己。

Reflection API以非常直觀的方式設計,并托管在java.lang.reflect包下。 它的結構嚴格遵循Java語言概念,并具有表示類(包括通用版本),方法,字段(成員),構造函數,接口,參數和注釋的所有元素。 Reflection API的入口點是Class< ? > Class< ? >類。 例如,列出String類的所有公共方法的最簡單方法是使用getMethods()方法調用:

final Method[] methods = String.class.getMethods(); for( final Method method: methods ) {System.out.println( method.getName() ); }

按照相同的原則,我們可以使用getFields()方法調用列出String類的所有公共字段,例如:

final Field[] fields = String.class.getFields(); for( final Field field: fields ) {System.out.println( field.getName() ); }

繼續使用反射對String類進行實驗,讓我們嘗試創建一個新實例,并在其上調用length()方法,所有這些僅使用反射API

final Constructor< String > constructor = String.class.getConstructor( String.class ); final String str = constructor.newInstance( "sample string" ); final Method method = String.class.getMethod( "length" ); final int length = ( int )method.invoke( str ); // The length of the string is 13 characters

反射最需要的用例可能圍繞注釋處理。 注釋本身(不包括Java標準庫中的注釋)對代碼沒有任何影響。 但是,Java應用程序可以在運行時使用反射來檢查它們感興趣的不同Java元素上存在的注釋,并根據注釋及其屬性應用某些邏輯。 例如,讓我們看一下自省的方式是否在類定義中存在特定的批注:

@Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.TYPE ) public @interface ExampleAnnotation {// Some attributes here }@ExampleAnnotation public class ExampleClass {// Some getter and setters here }

使用反射API ,可以使用getAnnotation()方法調用輕松完成。 返回的非null值表示存在注釋,例如:

final ExampleAnnotation annotation =ExampleClass.class.getAnnotation( ExampleAnnotation.class );if( annotation != null ) {// Some implementation here }

如今,大多數Java API都包含注釋,以方便開發人員使用和集成它們。 非常流行的Java規范的最新版本,例如RESTful Web服務的Java API ( https://jcp.org/en/jsr/detail?id=339 ), Bean驗證 ( https://jcp.org/en/jsr / detail?id = 349 ), Java臨時緩存API ( https://jcp.org/en/jsr/detail?id=107 ), Java消息服務 ( https://jcp.org/en/jsr/detail? id = 343 ), Java Persistence ( https://jcp.org/en/jsr/detail?id=338 )以及許多其他構建在注釋之上,它們的實現通常大量使用Reflection API來收集有關正在運行的應用程序。

3.訪問泛型類型參數

自從引入泛型(本教程的第4部分“ 如何和何時使用泛型”介紹了泛型 )以來, Reflection API已得到擴展,以支持對泛型類型的自省。 在許多不同的應用程序中經常彈出的用例是弄清楚用其聲明了特定類,方法或其他元素的通用參數的類型。 讓我們看一下示例類聲明:

public class ParameterizedTypeExample {private List< String > strings;public List< String > getStrings() {return strings;} }

現在,在使用反射檢查類時,非常容易知道將strings屬性聲明為具有String類型參數的泛型類型List 。 下面的代碼段說明了如何實現:

final Type type = ParameterizedTypeExample.class.getDeclaredField( "strings" ).getGenericType();if( type instanceof ParameterizedType ) {final ParameterizedType parameterizedType = ( ParameterizedType )type;for( final Type typeArgument: parameterizedType.getActualTypeArguments() ) {System.out.println( typeArgument );} }

以下通用類型參數將被打印在控制臺上:

class java.lang.String

4.反射API和可見性

在本教程的第1部分“ 如何創建和銷毀對象”中 ,我們第一次遇到了Java語言支持的可訪問性和可見性規則。 可能會令人驚訝,但是反射API能夠以某種方式修改給定類成員的可見性規則。

讓我們看一下帶有單個私有字段名稱的類的以下示例。 提供了此字段的getter,但沒有提供setter,這是有意為之。

public static class PrivateFields {private String name;public String getName() {return name;} }

顯然,對于任何Java開發人員而言,顯然都無法使用Java語言語法構造來設置name字段,因為該類無法提供實現此目的的方法。 關于救援的反射API ,讓我們看看如何通過更改字段的可見性和可訪問范圍來完成。

final PrivateFields instance = new PrivateFields(); final Field field = PrivateFields.class.getDeclaredField( "name" ); field.setAccessible( true ); field.set( instance, "sample name" ); System.out.println( instance.getName() );

以下輸出將打印在控制臺上:

sample name

請注意,如果沒有field.setAccessible( true )調用,則會在運行時引發異常,說明無法訪問帶有修飾符private的類的成員。

反射API的此功能通常由測試支架或依賴項注入框架使用,以便訪問內部(或不可暴露的)實現細節。 除非您別無選擇,否則請嘗試避免在應用程序中使用它。

5.反射API陷阱

另外,請注意,即使反射API非常強大,也有一些陷阱。 首先,它是安全權限的主題,可能并非在您的代碼正在其上運行的所有環境中都可用。 其次,它可能會對您的應用程序產生性能影響。 從執行前景來看,對反射API的調用非常昂貴。

最后, 反射API不能提供足夠的類型安全保證,迫使開發人員在大多數地方使用Object實例,并且在轉換構造函數/方法參數或方法返回值方面受到很大限制。

自Java 7發行以來,有一些有用的功能可以提供更快,另一種方式來訪問某些功能,這些功能以前只能通過反射調用來使用。 下一節將向您介紹它們。

6.方法句柄

Java 7版本向JVM和Java標準庫(方法句柄)引入了一個非常重要的新功能。 方法句柄是對基礎方法,構造函數或字段(或類似的低級操作)的類型化,直接可執行的引用,具有自變量或返回值的可選轉換。 從許多方面來看,它們是使用Reflection API執行的方法調用的更好替代方法。 讓我們看一下使用方法句柄動態調用String類上的方法length()的代碼片段。

final MethodHandles.Lookup lookup = MethodHandles.lookup(); final MethodType methodType = MethodType.methodType( int.class ); final MethodHandle methodHandle =lookup.findVirtual( String.class, "length", methodType ); final int length = ( int )methodHandle.invokeExact( "sample string" ); // The length of the string is 13 characters

上面的示例不是很復雜,只是概述了方法處理能力的基本概念。 請將其與使用“ 反射API ”部分中的“ 反射API”的相同實現進行比較。 但是,它看起來確實有些冗長,但是從性能和類型安全性角度來看,預期的方法句柄是更好的選擇。

方法句柄是非常強??大的工具,它們為在JVM平臺上有效實現動態(和腳本)語言提供了必要的基礎。 在本教程的第12部分“ 動態語言支持”中 ,我們將介紹其中的幾種語言。

7.方法參數名稱

Java開發人員多年來面臨的一個眾所周知的問題是,方法參數名稱在運行時沒有保留,而是被徹底清除了。 幾個社區項目,例如Paranamer ( https://github.com/paul-hammant/paranamer ),試圖通過向生成的字節碼中注入一些其他元數據來解決此問題。 幸運的是,Java 8通過引入新的編譯器參數–parameters改變了這一點,該–parameters將確切的方法參數名稱注入字節碼中。 讓我們看一下以下方法:

public static void performAction( final String action, final Runnable callback ) {// Some implementation here }

在下一步中,讓我們使用Reflection API檢查該方法的方法參數名稱,并確保保留它們:

final Method method = MethodParameterNamesExample.class.getDeclaredMethod( "performAction", String.class, Runnable.class ); Arrays.stream( method.getParameters() ).forEach( p -> System.out.println( p.getName() ) );

指定了-parameters編譯器選項后,以下參數名稱將被打印在控制臺上:

action callback

對于許多Java庫和框架的開發人員來說,這一期待已久的功能確實讓他們大為放松。 從現在開始,僅使用純Java 反射API即可提取更多有用的元數據,而無需引入任何其他變通方法(或黑客手段)。

8.接下來

在本教程的這一部分中,我們介紹了反射API ,它是檢查代碼,從代碼中提取有用的元數據甚至進行修改的方法。 盡管存在所有缺點,但反射API如今已在大多數(如果不是全部)Java應用程序中得到了廣泛使用。 在本教程的下一部分中,我們將討論Java中的腳本和動態語言支持。

9.下載源代碼

這是“ 反射”課程,是高級Java課程的第11部分。 您可以在此處下載源代碼: advanced-java-part-11

翻譯自: https://www.javacodegeeks.com/2015/09/how-to-use-reflection-effectively.html

總結

以上是生活随笔為你收集整理的如何有效地使用反射的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。