Java反射及註解

1、反射java

1.動態語言:是指程序在運行是能夠改變其結構:新的函數能夠引進,已有的函數能夠被刪除等結構上的變化。好比常見的JavaScript就是動態語言,除此之外Python等也屬於動態語言,而C、C++則不屬於動態語言。從反射角度說Java屬於半動態語言。程序員

2.反射機制:指在運行狀態中,對於任意一個類都可以知道這個類全部的屬性和方法;而且對於任意一個對象,都可以調用它的任意一個方法;這種動態獲取信息以及動態調用對象方法的功能稱爲Java語言的反射機制。安全

3.反射的應用場合
app

  編譯時類型和運行時類型ide

    在Java程序中許多對象在運行時都會出現兩種類型:編譯時類型和運行時類型。編譯時的類型由聲明對象時使用的類型來決定;運行時的類型由實際賦值給對象的類型決定。如:函數

    Person p = new Student();  其中編譯時類型爲Person,運行時類型爲Student。工具

  編譯時類型沒法獲取具體方法性能

    程序在運行時還可能接收到外部傳入的對象,該對象的編譯時類型爲Object,可是程序有須要調用該對象的運行時類型的方法。爲了解決這些問題,程序須要在運行時發現對象和類的真實信息。然而,若是編譯時根本沒法預知該對象和類屬於哪些類,程序只能依靠運行時信息來發現該對象和類的真實信息,此時就必須使用到反射了。ui

4.Java反射APIthis

反射API 用來生成JVM中的類、接口或對象的信息。 

  1)Class類:反射的核心類,能夠獲取類的屬性、方法等信息。

  2)Field類:Java.lang.reflect 包中的類,表示類的成員變量,能夠用來獲取和設置類中的屬性值。

  3)Method類:Java.lang.refect 包中的類,表示類的方法,能夠用來獲取類中的方法信息或執行方法。

  4)Constructor類:Java.lang.reflect 包中的類,表示類的構造方法。

5.反射使用步驟(獲取class對象、調用對象的方法)

  1)獲取想要操做的類的Class對象,它是反射的核心,經過Class對象咱們能夠任意調用類的方法。

  2)調用Class類中的方法,即就是反射的使用階段。

  3)使用反射API來操做這些信息。

6.獲取Class對象的3種方法

  調用某個對象的getClass()方法

    Person p = new Person();

    Class clazz = p.getClass();

  調用某個類的class屬性來獲取該類對應的Class對象

    Class clazz = Person.class;

  使用Class 類中的forName()靜態方法(最安全/性能最好)

    Class clazz = Class.forName("類的全路徑");

 1 當咱們得到了想要操做的類的 Class 對象後,能夠經過 Class 類中的方法獲取並查看該類中的方法和屬性。  2 //獲取 Person 類的 Class 對象
 3 Class clazz=Class.forName("reflection.Person");  4 //獲取 Person 類的全部方法信息
 5 Method[] method=clazz.getDeclaredMethods();  6 for(Method m:method){  7  System.out.println(m.toString());  8 }  9 //獲取 Person 類的全部成員屬性信息
10 Field[] field=clazz.getDeclaredFields(); 11 for(Field f:field){ 12  System.out.println(f.toString()); 13 } 14 //獲取 Person 類的全部構造方法信息
15 Constructor[] constructor=clazz.getDeclaredConstructors(); 16 for(Constructor c:constructor){ 17  System.out.println(c.toString()); 18 }

7.建立對象的兩種方法

  Class 對象的newInstance()

    1)使用Class對象的newInstance()方法來建立該Class對象對應類的實例,可是這種方法要求該Class對象對應的類有默認的空構造器。

  調用Constructor對象的newInstance()

    2)先使用Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來建立Class對象對應類的實例,經過這種方法能夠選定構造方法建立實例。

1 //獲取 Person 類的 Class 對象
2 Class clazz=Class.forName("reflection.Person"); 3 //使用.newInstane 方法建立對象
4 Person p=(Person) clazz.newInstance(); 5 //獲取構造方法並建立對象
6 Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); 7 //建立對象並設置屬性
8 Person p1=(Person) c.newInstance("李四","男",20);

8.JDK動態加載

  Java反射機制容許程序在運行時加載、探知、使用編譯期間徹底未知的classes。經過Java的反射機制,能夠得到程序內部或第三方JAR包的Class、Method、屬性、參數等信息。

  動態加載:程序在運行時調用相應方法,即便其餘方法是錯誤的,程序依舊會執行。

  靜態加載:程序在編譯時執行,在執行過程當中加載全部可能執行到的程序。在這種加載方式下,只要加載中一個方法出錯,程序就不能運行。

2、Java註解

1.概念

  Annotation(註解)是Java提供的一種對源程序中元素關聯信息和元數據(metadata)的途徑和方法。Annotation(註解)是一個接口,程序能夠經過反射來獲取制定程序中元素的Annotation對象,而後經過該Annotation對象來獲取註解中的元數據信息。

2. 四種標準元註解

元註解做用是負責註解其餘註解。Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其餘annotation類型做說明。

  @Target  修飾的對象範圍

    @Target說明了annotation所修飾的對象範圍:annotation可被用於packages、types(類、接口、枚舉、annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。在annotation類型的聲明中使用了target可更加明晰其修飾的目標。

  @Retention 定義被保留的時間長短

    Retention定義了該annotation被保留的時間長短:表示須要在什麼級別保存註解信息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效),取值(RetentionPoicy)有:

      SOURCE:在源文件中有效(即源文件保留)

      CLASS:在class文件中有效(即class保留)

      RUNTIME:在運行時有效(即運行時保留)

  @Documented 描述-javadoc

    @Documented用於描述其餘類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。

  @Inherited 闡述了某個被標註的類型是被繼承的

    @Inherited元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。

3.註解處理器

  若是沒有用來讀取註解的方法和工做,那麼註解也就不會比註釋更有用處了。使用註解的過程當中,很重要的一部分就是建立與使用註解處理器。Java SE5擴展了反射機制的API,以幫助程序員快速的構造自定義註解處理器。下面實現一個註解處理器。

 1  /1:*** 定義註解*/
 2 @Target(ElementType.FIELD)  3 @Retention(RetentionPolicy.RUNTIME)  4 @Documented  5 public @interface FruitProvider {  6      /**供應商編號*/
 7     public int id() default -1;  8     /*** 供應商名稱*/
 9     public String name() default ""10     /** * 供應商地址*/
11     public String address() default ""; 12 } 13 //2:註解使用
14 public class Apple { 15      @FruitProvider(id = 1, name = "陝西紅富士集團", address = "陝西省西安市延安路") 16      private String appleProvider; 17      public void setAppleProvider(String appleProvider) { 18          this.appleProvider = appleProvider; 19  } 20      public String getAppleProvider() { 21          return appleProvider; 22      
23 } 24 /3:*********** 註解處理器 ***************/
25 public class FruitInfoUtil { 26      public static void getFruitInfo(Class<?> clazz) { 27      String strFruitProvicer = "供應商信息:"; 28      Field[] fields = clazz.getDeclaredFields();//經過反射獲取處理註解
29      for (Field field : fields) { 30          if (field.isAnnotationPresent(FruitProvider.class)) { 31              FruitProvider fruitProvider = (FruitProvider) field.getAnnotation(FruitProvider.class);//註解信息的處理地方 
32         strFruitProvicer = " 供應商編號:" + fruitProvider.id() + " 供應商名稱:"
33           + fruitProvider.name() + " 供應商地址:"+ fruitProvider.address(); 34       System.out.println(strFruitProvicer); 35  } 36  } 37  } 38 } 39 public class FruitRun { 40      public static void main(String[] args) { 41          FruitInfoUtil.getFruitInfo(Apple.class); 42 /***********輸出結果***************/
43 // 供應商編號:1 供應商名稱:陝西紅富士集團 供應商地址:陝西省西安市延
44  } 45 }
相關文章
相關標籤/搜索