注解

注解概述

JDK5 开始,Java 增加对 元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,可以在 编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在 不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。应用于 包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。
本质上是一个继承了 Annotation 的特殊接口。

元注解

注解之上的注解,用来定义注解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

元注解有六种:

  1. @Target:什么 地方使用该注解
  2. ElementType.CONSTRUCTOR:用于描述构造器
  3. ElementType.FIELD:成员变量、对象、属性(包括enum实例)
  4. ElementType.LOCAL_VARIABLE:用于描述局部变量
  5. ElementType.METHOD:用于描述方法
  6. ElementType.PACKAGE:用于描述包
  7. ElementType.PARAMETER:用于描述参数
  8. ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
  9. @Retention: 什么 时候使用该注解
  10. RetentionPolicy.SOURCE:在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
  11. RetentionPolicy.CLASS:在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
  12. RetentionPolicy.RUNTIME :始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
  13. @Documented:注解是否将包含在JavaDoc中
  14. @Inherited:是否允许子类继承该注解
  15. @Repeatable:1.8 新增,允许一个注解在一个元素上使用多次
  16. @Native:1.8新增,修饰成员变量,表示这个变量可以被本地代码引用,常常被代码生成工具使用

JDK内置注解

  • @Override :方法重写
  • @Deprecated:表示方法已经过时,方法上有横线,使用时会有警告。
  • @SuppressWarnings:表示关闭一些警告信息(通知java编译器忽略特定的编译警告)
  • @SafeVarargs: (jdk1.7更新) 表示:专门为抑制”堆污染”警告提供的。
  • @FunctionalInterface:(jdk1.8更新) 表示:用来指定某个接口必须是函数式接口,只能有一个需要实现的抽象方法,否则就会编译出错。

自定义注解

自定义注解规则

  • 自定义注解需要添加元注解
  • 所有 Annotation 定义类型为 @interface,会自动继承 java.lang.Annotaion 这个接口,并且不能再去继承别的类或是接口。
  • 参数成员只能用 public 或默认(default) 这两个访问权修饰。
  • 参数成员只能是 byte、short、char、int、long、float、double、boolean 八种基本数据类型和 String、Enum、Class、annotations 等数据类型,以及这一些类型的数组.

  • 要获取类方法和字段的注解信息,必须通过 Java 的 反射技术来获取 Annotation 对象,因为除此之外没有别的获取注解对象的方法

  • 注解也可以没有定义成员,不过这样注解就没啥用了

创建自定义注解

需求:

创建一个注解,用于添加在字段上,可以起到给字段赋值的作用

步骤:

  1. 创建注解
import java.lang.annotation.*;

// 作用于字段
@Target(ElementType.FIELD)
// 运行期间有效
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
    // 类型 属性名 默认属性值
    String value() default "龙傲天";
}
  1. 创建实体类
public class User {

    @AnnotationDemo("李四")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  1. 利用反射注解解析并赋值
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static Object getObject(String className) throws ClassNotFoundException,  NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName(className);
        Object obj = clazz.newInstance();
        Field[] declaredFields = clazz.getDeclaredFields();
        // 遍历所有字段
        for (Field field : declaredFields) {
            // 判断字段上是否添加有此注解
            if (field.isAnnotationPresent(AnnotationDemo.class)){
                // 获得该字段上存在的该注解对象
                AnnotationDemo annotation = field.getAnnotation(AnnotationDemo.class);
                // 获得字段的名称
                String fieldName = field.getName();
                // 得到修改该字段的方法
                Method setMethod = clazz.getDeclaredMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), String.class);
                // 调用该方法,传入注解的值
                setMethod.invoke(obj,annotation.value());
            }
        }
        return obj;
    }
}
  1. 测试
import java.lang.reflect.InvocationTargetException;

public class Method {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException {
        User user = (User) Test.getObject("com.dong.User");
        System.out.println(user);
    }
}
  1. 输出
User{name='李四'}

Original: https://www.cnblogs.com/suwuji/p/16627633.html
Author: 苏无及
Title: 注解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/613166/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球