一、反射
1. 什么是反射
-
反射:是一種機制,利用該機制可以在程序運行過程中對類進行解剖並操作類中的方法,屬性,構造方法等成員。
-
是另外一種調用構造方法、普通方法、屬性的方式。
-
對比普通方式:
-
功能更強
-
但是更麻煩
-
反射操作的統一步驟:
獲取Class字節碼對象
要操作什么,就獲取什么:getxxx(), getDeclaredXXX()
要操作構造方法,就獲取Constructor對象
要操作普通方法,就獲取Method對象
要操作屬性字段,就獲取Field對象
如果操作是private類型,就提前設置允許暴力反射:setAccessible(true)
反射調用
反射調用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 基本語法
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. 獲取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) -
BeanUtils的使用:
-
BeanUtils.setProperty(bean, fieldName, fieldValue)
-
BeanUtils.getProperty(bean, fieldName)
-
BeanUtils.populate(bean, map)
-
-
注解:
-
能說出一些JDK提供的注解:@author, @version, @Override, @Deprecated, @SupressWarning
-
了解元注解及其作用:
-
@Target:限制自定義 注解用在什么地方,從ElementType里取值
-
@Retention:限制自定義注解保留到什么階段(生命周期),從RetentionPolicy里取值
-
-
掌握注解的使用:
-
@注解名(屬性名=值, 屬性名=值,....)
-
如果屬性有默認值,可以不設置值
-
如果只有一個屬性要設置值,並且屬性名稱是value,可以簡寫成:@注解名(value的值)
-
-
了解注解的解析:
-
method.isAnnotationPresent(Class annotationClass)
:判斷方法上是否有指定注解
-
-