自定义注解

一、定义

用来说明程序地一个标识,给计算机看的。注解也叫元数据,是一种代码级别的说明。它是JDK1.5之后引入地一个特性,是一种特殊地接口,可以使用在字段、类、方法、包参数等上面。
注意:注解本身并没有任何功能,仅仅起到一个标识性地作用。我们通过反射获得注解,再根据是否有这个注解、注解中的一些属性去判断,执行哪种业务逻辑。

二、自定义注解

1) 语法

注解的关键字为@interface。在底层实现上,所有定义的注解都会自动继承java.lang.annotation.Annotation接口。

//此处为元注解
public @interface MyAnnotation {
    //此处为属性列表
    String name() ;
    int age() default 18;
    String[] favoriteFood();
}
2)属性
  • 注解的属性本质为接口中的抽象方法,默认值用default指定
  • 属性只能是以下数据类型
    a. 基本数据类型
    b. String
    c. 枚举
    d. 注解
    e. 以上类型的数组
  • 如果定义了属性,在使用的时候需要给属性赋值
  • 如果只有一个属性, 可以把这个属性名字定义为value,这样使用的时候可以省略属性名
  • 数组属性的值要用 {} 包裹,如果数组只有一个值,那么 {} 可以省略
  • 如果注解本身没有属性,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效
3)元注解

用于描述注解的注解
a. @Targer: 描述该注解的作用范围, 用枚举类ElementType定义类型如下

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

b. @Retention: 描述注解被保留的阶段
RetentionPolicy.RUNTIME: 会保留到class字节码文件中,被jvm读取。 基本用该类型
c. @Documented: 描述注解是否被抽取到api文档中。一般不用
d. @Inherited: 描述注解是否可以被继承。一般不继承

三、自定义注解的使用

  1. 定义注解:相当于定义标记;
  2. 配置注解:把标记打在需要用到的程序代码中;
  3. 解析注解:在编译期或运行时检测到标记,并进行特殊操作。
public class AnnationClientTest {
    @Test
    public void testAnnation() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class studentClass = Class.forName("com.javalearning.School");
        Field[] snames = studentClass.getDeclaredFields();
        for (Field sn : snames) {
            if (sn.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = sn.getAnnotation(MyAnnotation.class);
                if (annotation != null) {
                    System.out.println(annotation.name() + annotation.age() + annotation.favoriteFood());
                }
            }
        }
        System.out.println(studentClass);
    }
}
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
//元注解
public @interface MyAnnotation {
    //属性列表
    String name() ;
    int age() default 18;
    String[] favoriteFood();
}
public class School {
    @MyAnnotation(name="Vivi", favoriteFood = {"banana, pineapple, cucumber"})
    private String schoolName;
    ...
}
  • 如果要获得的注解是配置在方法上,那么要从Method对象上获取;如果配置在属性上,就从该属性对应的Field对象上去获取,如果配置在类型上,需要从Class对象上去获取。
  • isAnnotationPresent()方法是判断该元素上是否配置有某个指定的注解;
  • getAnnotation()方法是获取该元素上指定的注解。之后再调用该注解的注解类型元素方法就可以获得配置时的值数据;
  • 反射对象上还有一个方法getAnnotations(),该方法可以获得该对象身上配置的所有的注解。它会返回给我们一个注解数组,需要注意的是该数组的类型是Annotation类型,这个Annotation是一个来自于java.lang.annotation包的接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值