反射和注解的使用


 

一、反射

1. 什么是反射

  • 反射:是一種機制,利用該機制可以在程序運行過程中對類進行解剖並操作類中的方法,屬性,構造方法等成員。

  • 是另外一種調用構造方法、普通方法、屬性的方式。

  • 對比普通方式:

    • 功能更強

    • 但是更麻煩

反射操作的統一步驟:

  1. 獲取Class字節碼對象

  2. 要操作什么,就獲取什么:getxxx(), getDeclaredXXX()

    • 要操作構造方法,就獲取Constructor對象

    • 要操作普通方法,就獲取Method對象

    • 要操作屬性字段,就獲取Field對象

  3. 如果操作是private類型,就提前設置允許暴力反射:setAccessible(true)

  4. 反射調用

    • 反射調用Constructor:newInstance()

    • 反射調用Method:invoke()

    • 反射調用Filed: set(), get()

2. Class對象

2.1 如何獲取一個類的Class對象

//1. 類名.class
Class clazz = Student.class;

//2. 對象.getClass()
Class clazz = student.getClass();

//3. 靜態方法Class.forName("全限定類名")
Class clazz = Class.forName("com.itheima._01reflect.Student");

2.2 Class對象的常用方法


//獲取簡單類名:不包含包的類名
String simpleName = clazz.getSimpleName();

//獲取全限定類名
String name = clazz.getName();

//生成類的實例對象
Object object = clazz.newInstance();

3. Constructor對象

3.1 獲取到Constructor對象

  • clazz.getConstructor(Class... parameterTypes):獲取public類型的Constructor對象

    • 參數parameterTypes:構造方法的參數類型

  • clazz.getDeclaredConstructor(Class... parameterTypes):獲取任意類型的Constructor對象

  • clazz.getConstructors():獲取所有的public類型Constructor數組

  • clazz.getDeclaredConstructors():獲取所有任意類型的Constructor數組


//1. 獲取public類型的構造方法
Constructor constructor = clazz.getConstructor(String.class, Integer.class);
//2. 獲取private類型的構造方法
Constructor constructor = clazz.getDeclaredConstructor();

3.2 反射調用Constructor生成類實例

  • constructor.newInstance(Object... parameterValues):反射調用構造方法,生成類實例對象

    • 參數parameterValues:構造方法需要的實參值

    注意:只能操作public類型的構造方法,如果要操作private類型的,需要提前設置暴力反射

  • setAccessible(true):設置允許暴力反射

4. Method對象

4.1 獲取Method對象

  • clazz.getMethod(String methodName, Class... parameterTypes):獲取public類型的方法

  • clazz.getDeclaredMethod(String methodName, Class... parameterTypes):獲取任意類型的方法

  • clazz.getMethods():獲取所有的public類型方法(自己的,和父類 的)

  • clazz.getDeclaredMethods():獲取所有的任意類型方法(自己的)


Class<Student> clazz = Student.class;

//獲取student里的study方法:public, 無參
Method method = clazz.getMethod("study");
//獲取student里的eat方法:private,無參
method = clazz.getDeclaredMethod("eat");
//獲取student里的sleep方法:public,有參:String
method = clazz.getMethod("sleep", String.class);

4.2 反射調用Method

  • method.invoke(Object target, Object... parameterValues):反射調用方法

    • 參數:

      • target:調用哪個對象的方法

      • parameterValues:方法的實參

    • 返回值:方法執行的返回值

    只能調用public類型的方法。如果要調用private類型的,需要提前設置:允許暴力反射

  • setAccessible(true):設置允許暴力反射

5. Field對象

5.1 獲取Field對象

  • clazz.getField(String fieldName):獲取public類型的屬性

  • clazz.getDeclaredField(String fieldName):獲取任意類型的屬性

  • clazz.getFields():獲取所有public類型的屬性數組

  • clazz.getDeclaredFields():獲取所有任意類型的屬性數組


//獲取Class對象
Class<Student> clazz = Student.class;
//獲取屬性的Field對象:name,private
Field field = clazz.getDeclaredField("name");
//獲取屬性的Field對象:sex,public
field = clazz.getField("sex");

5.2 反射操作Field對象

  • field.set(Object target, Object value):設置屬性值

    • 參數:

      • target:設置哪個對象的屬性值

      • value:要設置的屬性值

  • field.get(Object target):獲取屬性值

    • 參數:

      • target:獲取哪個對象的屬性值

    • 返回值:

      • 屬性值,Object


Student student1 = new Student("老王");
Student student2 = new Student("老李");


//獲取Class對象
Class<Student> clazz = Student.class;
//獲取name的Field對象
Field field = clazz.getDeclaredField("name");

field.setAccessible(true);

//1. 設置student1的name的屬性值
field.set(student1, "老趙");
System.out.println(student1);

//2. 獲取student2的name屬性值
Object fieldValue = field.get(student2);
System.out.println(fieldValue);

 

二、BeanUtils

1. BeanUtils簡介

  • BeanUtils:Apache的commons項目提供的一個工具包,簡化了JavaBean的封裝。

  • 相關概念:

    • 字段:類里的成員變量名

    • 屬性:get/set方法,去年前綴,首字母小寫是屬性

    注意:創建的字段,建議使用idea的快捷鍵生成get/set方法==>保證了字段名和屬性名一致

  • 相關jar包:

2. BeanUtils的使用

  • BeanUtils.setProperty(Object bean, String fieldName, Object fieldValue):設置屬性值

  • BeanUtils.getProperty(Object bean, String fieldName):獲取屬性值

  • BeanUtils.populate(Object bean, Map<String, Object> map):把map里的數據封裝成JavaBean

三、注解

1. 什么是注解

1.1 注解簡介

  • 注解:Annotation,是JDK1.5提供的新特性。

  • 注解:是一種和class、interface同一等級的語法說明,是一種記號(標記)。本身沒有功能,其它程序、工具根據記號提供不同的功能。

1.2 常見注解和作用

  • 作用:

    • 輔助生成文檔的:

      • @Documented

      • @author:作者

      • @version:版本(代碼的版本,而不是jdk的版本)

    • 編譯檢查:

      • @Override:方法是重寫的方法。添加之后,idea/eclipse會檢查語法是否正確

      • @Deprecated:標記方法已過時。標記之后,idea/eclipse會給這些方法的使用加上刪除線

      • @SupressWarning:壓制警告。標記之后,idea/eclipse不再顯示警告信息

    • 代替xml配置文件:

      • @WebServlet:(Tomcat提供的注解)配置一個Servlet的信息的,早期是使用web.xml配置

  • 注意:

    • 注解本身沒有功能;其它軟件、其它程序、其它框架會根據注解,設置功能

2. 自定義注解(了解)

2.1 基本語法


@元注解
public @interface 注解名{
   屬性類型 屬性名() default 默認值;
}

2.2 元注解

  • 元注解:JDK提供的,用來限制自定義注解的注解。

  • 常見的有2個:

    • @Target:用來限制自定義注解可以用在什么地方。從ElementType里取值,常用值有:

      • ElementType.TYPE:可以用在類、接口上

      • ElementType.METHOD:可以用在方法上

      • ElementType.FIELD:可以用在成員變量上

    • @Retention:用來限制自定義注解的生命周期(保留到什么階段)。從RetentionPolicy里取值,常用的有:

      • RetentionPolicy.SOURCE:自定義注解保留到源碼階段。 字節碼和運行階段不存在的

      • RetentionPolicy.CLASS:自定義注解保留到字節碼階段。在運行階段是不存在原

      • RetentionPolicy.RUNTIME:自定義注解保留到運行階段。所有階段都存在

2.3 屬性

  • 注解的屬性,並非任意屬性都可以。支持的屬性有:

    • 8種基本數據類型

    • String

    • Class

    • 枚舉

    • 注解

    • 以上類型的數組形式

3. ==注解的使用==

  • @注解名(屬性名=值, 屬性名=值, ...)

  • 注意:

    • 如果屬性有默認值,使用屬性時可以不設置值

    • 如果只有一個屬性要設置值,並且屬性名稱是value,使用注解時可以簡寫成:@注解名(值)

4. 注解的解析(了解)

  • 自定義注解必須要保留到運行階段,才可以解析

  • method.isAnnotationPresent(Class annotationClass):判斷方法上是否有指定的注解

 

內容總結

  1. 反射:掌握反射的統一步驟


    1. 獲取Class對象
    2. 要操作什么,就獲取什么:clazz.getXXX(), clazz.getDeclaredXXX()
    構造方法:Constructor對象
    普通方法:Method對象
    字段屬性:Field對象
    3. 如果是private類型的,反射之前,要允許暴力反射:xxx.setAccessible(true)
    4. 反射操作
    構造方法的反射調用:constructor.newInstance(Object... parameterValues)
    普通方法的反射調用:method.invoke(Object target, Object... paramaterValues)
    字段屬性的反射調用:
    field.set(Object target, Object value),
    field.get(Object target)
  2. BeanUtils的使用:

    • BeanUtils.setProperty(bean, fieldName, fieldValue)

    • BeanUtils.getProperty(bean, fieldName)

    • BeanUtils.populate(bean, map)

  3. 注解:

    1. 能說出一些JDK提供的注解:@author, @version, @Override, @Deprecated, @SupressWarning

    2. 了解元注解及其作用:

      • @Target:限制自定義 注解用在什么地方,從ElementType里取值

      • @Retention:限制自定義注解保留到什么階段(生命周期),從RetentionPolicy里取值

    3. 掌握注解的使用:

      • @注解名(屬性名=值, 屬性名=值,....)

      • 如果屬性有默認值,可以不設置值

      • 如果只有一個屬性要設置值,並且屬性名稱是value,可以簡寫成:@注解名(value的值)

    4. 了解注解的解析:

      • method.isAnnotationPresent(Class annotationClass):判斷方法上是否有指定注解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM