注解与反射

拼搏现实的明天。 2021-09-25 08:32 492阅读 0赞

注解与反射

  • 注解 Annotation
    • 什么是注解
    • 注解分类
      • 内置注解
      • 元注解
        • @Target
        • @Retention
        • @Documented
        • @Inherited
      • 自定义注解
        • 示例
  • 反射 Reflect
    • 什么是反射
    • 常用方法
      • 获取Class类
      • 获取实例
      • 操作方法
      • 操作属性
      • 操作泛型
      • 操作注解

注解 Annotation

什么是注解

说白了就是对程序的解释,其实跟注释是一个含义,但是注解可以被程序读取,进行后续处理。

注解分类

内置注解

JDK自带的注解,包括常见的@Override(方法重写)、@Deprecated(方法弃用)、 @SuperWarnings(忽略警告) 等等。

元注解

修饰注解的注解,称之为元注解。
常用的元注解有以下几类。

@Target

注解可以修饰哪些元素。






































ElementType 作用域
PACKAGE
CONSTRUCTOR 构造器
FIELD 属性
LOCAL_VARIABLE 局部变量
METHOD 方法
PARAMETER 参数
TYPE 类、接口、注解、枚举

@Retention

指明该注解的生命周期






















RetentionPolicy 作用
SOURCE 在源文件中有效(即源文件保留)
CLASS 在class文件中有效(即class保留)
RUNTIME 在运行时有效(即运行时保留)注:为RUNTIME时可以被反射机制所读取

@Documented

使用此修饰的注解将会被 javadoc 工具提取成文档,使用此注解,其 @Retention 必须被设置为 RetentionPolicy.RUNTIME

@Inherited

使得注解具有继承性。

自定义注解

  • 使用@interface 关键词,自动继承了java.lang.annotation.Annotation接口
  • 返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value

示例

自定义注解

  1. // 可作用于类、方法、字段
  2. @Target({ ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
  3. @Retention(RetentionPolicy.RUNTIME)
  4. public @interface MyAnntation{
  5. // 如果没有default,那么在使用这个注解时,必须传递这些参数
  6. String name() default "";
  7. int length() default 0;
  8. }

实体类

  1. // lombok的注解
  2. @Data
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. @MyAnntation(name = "user",length = 10)
  6. public class User {
  7. @MyAnntation(name = "id",length = 32)
  8. private String userId;
  9. @MyAnntation(name = "userName", length = 50)
  10. private String userName;
  11. private String sex;
  12. private String idCard;
  13. private String note;
  14. private String id;
  15. @MyAnntation()
  16. public void func(){
  17. }
  18. public List<String> func2(Map<String,Object> map,Integer i){
  19. return null;
  20. }
  21. }

反射 Reflect

什么是反射

反射指的是程序在运行期间借助反射 API 取得任何类的内部信息,并通过这些内部信息去操作对应对象的内部属性和方法。
任何一个类,在第一次使用时,就会被 JVM 加载到堆内存的方法区中。JVM 加载类成功后,就会在方法区中产生一个对应的 Class 对象(一个类只要一个 Class 对象),这个 Class 对象包含被加载类的全部结构信息。

常用方法

获取Class类

  1. // 方法一
  2. Class c1 = Class.forName("com.xxx.User");
  3. // 方法二
  4. Class c2 = User.class;
  5. // 方法三
  6. User user = new User();
  7. Class c3 = user.getClass();
  8. // 获取类名
  9. String name = c1.getName();

获取实例

  1. // 通过无参构造获取实例对象
  2. User u1 = (User) c1.newInstance();
  3. // 如果没有无参构造,可以通过带参构造获取实例对象
  4. Constructor con = c1.getDeclaredConstructor(String.class,String.class,String.class,String.class,String.class,String.class);
  5. User u2 = (User) con.newInstance("no001","xzy","","","","");

操作方法

  1. // 获取所有方法 只包含public的方法以及父类的public方法
  2. Method[] mArr1 = c1.getMethods();
  3. // 获取所有方法 包含私有方法
  4. Method[] mArr2 = c1.getDeclaredMethods();
  5. // 获取指定名称的方法
  6. Method getId = c1.getDeclaredMethod("getId");
  7. // 方法名称,参数类型
  8. Method setId = c1.getDeclaredMethod("setId", String.class);
  9. // 调用setId方法
  10. // @Param 对象
  11. // @Param 参数
  12. setId.invoke(u1, "NO001");
  13. String id = getId.invoke(u1);

操作属性

  1. // 获取public属性
  2. c1.getFields();
  3. // 获取所有属性
  4. c1.getDeclaredFields();
  5. // 获取指定属性
  6. Field userName = c1.getDeclaredField("userName");
  7. // 加上这个访问权限即可,不加会报错 Class com.xxx.reflect.ReflectClass can not access a member of class com.xxx.pojo.User with modifiers "private"
  8. userName.setAccessible(true);
  9. userName.set(user,"xzy");
  10. String name = (String) userName.get(user);
  11. System.out.println(name);

操作泛型

  1. // 先获取方法
  2. Method method = c1.getDeclaredMethod("func2", Map.class,Integer.class);
  3. // 获取方法参数类型 java.util.Map<java.lang.String, java.lang.Object> java.lang.Integer
  4. Type[] genericParameterTypes = method.getGenericParameterTypes();
  5. for (Type genericParameterType : genericParameterTypes) {
  6. System.out.println(genericParameterType);
  7. // 若属于参数化类型,则获取类型对象的数组,表示此类型的实际类型参数
  8. if(genericParameterType instanceof ParameterizedType){
  9. Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
  10. for (Type actualTypeArgument : actualTypeArguments) {
  11. //打印下实际类型参数
  12. System.err.println(actualTypeArgument);
  13. }
  14. }
  15. }

操作注解

  1. // 获取所有注解
  2. Annotation[] arr = c1.getDeclaredAnnotations();
  3. for (Annotation annotation : arr) {
  4. System.out.println(annotation);
  5. }
  6. // 获取指定的注解
  7. MyAnntation annotation = (MyAnntation) c1.getDeclaredAnnotation(MyAnntation.class);
  8. // 输出注解的属性值
  9. System.out.println(annotation.name());
  10. System.out.println(annotation.length());
  11. // 获取字段上的注解
  12. Field userName = c1.getDeclaredField("userName");
  13. MyAnntation fliedAnn = userName.getAnnotation(MyAnntation.class);
  14. System.out.println(fliedAnn.name());
  15. System.out.println(fliedAnn.length());
  16. // 获取方法上的注解
  17. Method f1 = c1.getDeclaredMethod("func");
  18. MyAnntation fAnn = f1.getAnnotation(MyAnntation.class);
  19. System.out.println(fAnn.name());

发表评论

表情:
评论列表 (有 0 条评论,492人围观)

还没有评论,来说两句吧...

相关阅读

    相关 注解反射

    注解(Annotation)是Java中的一种元数据,它提供了一种为程序元素(类、方法、变量等)添加元数据的方式。注解可以用来描述程序元素的特性、用途和约束条件等信息。Java

    相关 注解反射

    注解(Annotation)是Java中的一种元数据,它提供了一种为程序元素(类、方法、变量等)添加元数据的方式。注解可以用来描述程序元素的特性、用途和约束条件等信息。Java

    相关 注解反射

    注解 什么是注解 Annotation(注解)是从JDK5.0开始引入的新技术 注解可以被其他程序(如:编译器等)读取,不是程序本身,可以对程序做出解释

    相关 反射注解

    反射与注解 一、反射 1. 使用反射机制可以动态的获取当前class的信息,比如方法的信息、注解信息、方法的参数、属性 2. 反射目的:方便开发者对框架的拓展,

    相关 JAVA反射注解

    JAVA反射与注解 前言 现在在我们构建自己或公司的项目中,或多或少都会依赖几个流行比较屌的第三方库,比如:Butter Knife、Retrofit 2、Dagge