自定义注解

什么是元注解

java提供了四种元注解,专门用来注解其他的注解

  • @Documented –注解是否将包含在JavaDoc中

  • @Retention –什么时候使用该注解,即该注解的生命周期。

    • RetentionPolicy.SOURCE 只在源码显示,编译时丢弃 比如override注解

    • RetentionPolicy.CLASS 编译时记录到class中,运行时忽略

    • RetentionPolicy.RUNTIME 运行时存在,可以通过反射读取

  • @Target -注解用于什么地方,即该注解的作用域,作用域可以同时存在多个

    • ElementType.TYPE(类,接口,枚举)

    • ElementType.FIELD(字段声明)

    • ElementType.METHOD(方法声明)

    • ElementType.PARAMETER(参数声明)

    • ElementType.CONSTRUCTOR(构造方法声明)

    • ElementType.LOCAL VARIABLE(局部变量声明)

    • ElementType.ANNOTATION_TYPE(注解)

    • ElementType.PACKAGE(包声明)

    • ElementType.TYPE_PARAMETER(jdk1.8开始提供的类型参数)

    • ElementType.TYPE_USE(jdk1.8开始提供的类型)

  • @Inherited – 是否允许子类继承该注解,该注解只有在类上使用时才会有效,对方法,属性等其他无效。

自定义注解

自定义注解类编写的一些规则:

  1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。

  2. 参数成员只能用public或默认(default)这两个访问权修饰

  3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组

  4. 在使用注解的时候成员必须赋值

  5. value是一个特殊的参数名,在其他参数有默认值时或没有其他参数时,注解仅为value赋值时,可省略value定义,直接赋值。比如:@RequestMapping("/test")

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

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

自定义注解实例

  1. 定义类级别的TypeAnnotationTest

import java.lang.annotation.*;
​
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TypeAnnotationTest {
     String value();
}

该注解使用的时候,在“运行时”有效,只能定义在“类”上,可以“被子类继承”,能“生成javadoc”,使用的时候可以省略value定义

  1. 定义方法级别的MethodAnnotationTest

import java.lang.annotation.*;
​
​
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodAnnotationTest {
    String testValue() default "" ;
}

该注解使用的时候,在“运行时”有效,只能定义在“方法”上,能“生成javadoc”,使用的时候必须加上testValue定义

  1. 定义一个父类

@TypeAnnotationTest("parent annotation")
public class Parent {
​
    @MethodAnnotationTest(testValue="parent sayHello method")
    public void sayHello(){
        System.out.println("hello");
    }
}

这里TypeAnnotationTest使用的时候就省略了value定义,注意这里sayHello方法是public的

  1. 定义一个子类

public class Child extends Parent {
​
    @MethodAnnotationTest(testValue="child sayHello method")
    private String childSayHello(String msg){
        return "child say:" +msg;
    }
}

注意这里sayHello方法是private的

  1. 编写Test类

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
​
public class Test {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("Child");
            // 找到类上面的注解
            boolean isExist = clazz.isAnnotationPresent(TypeAnnotationTest.class);
            if (isExist) {
                TypeAnnotationTest typeAnnotation = (TypeAnnotationTest) clazz.getAnnotation(TypeAnnotationTest.class);
                System.out.println(typeAnnotation.value());
            }
​
​
​
            // getDeclaredMethods能拿到所有(不包括继承的方法),而getMethods只能拿到public方法(包括继承的类或接口的方法)
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                Annotation[] annotations = method.getAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof MethodAnnotationTest) {
                        System.out.println(((MethodAnnotationTest) annotation).testValue());
                    }
                }
            }
​
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
  1. 结果输出

parent annotation
child sayHello method

将clazz.getDeclaredMethods();替换成clazz.getMethods();则输出

parent annotation
parent sayHello method


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值