反射和注解的使用
Posted penghuake
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射和注解的使用相关的知识,希望对你有一定的参考价值。
一、反射
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)
:判断方法上是否有指定注解
-
-
以上是关于反射和注解的使用的主要内容,如果未能解决你的问题,请参考以下文章