反射和注解的使用

 

一、反射

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):判断方法上是否有指定注解

猜你喜欢

转载自www.cnblogs.com/penghuake/p/10886322.html