java-注解

目录

一、元注解

@Target

@Documented

@Inherited

@Retention

二、自定义注解

三、注解信息的获取

一、元注解

定义:修饰注解的注解叫做元注解

@Target

指定注解的使用范围,不写默认可使用在任何地方(除了自定义类型声明语句、成员变量上的泛型,需指定ElementType.TYPE_PARAMETER、ElementType.TYPE_USE)

可通过ElementType来限制注解的使用范围

public enum ElementType {
    /* 类、接口(包括注解类型)或枚举声明 */
    TYPE,
    /* 字段声明(包括enum常量) 就是成员变量 */
    FIELD,
    /* 方法声明 */
    METHOD,
    /* 正式的参数声明 */
    PARAMETER,
    /* 构造函数声明 */
    CONSTRUCTOR,
    /* 局部变量声明 */
    LOCAL_VARIABLE,
    /* 注解类型声明 */
    ANNOTATION_TYPE,
    /* 包声明 */
    PACKAGE,
    /* 类型参数声明 jdk1.8及以后 */
    TYPE_PARAMETER,
    /** 类型的使用 jdk1.8及以后 */
    TYPE_USE
}

    TYPE_PARAMETER:可以使用在自定义类型参数(可以是javaBean或者枚举等)的声明语句

若想在类声明语句中的泛型上调用注解,得加上TYPE_PARAMETER

 

    TYPE_USE:表示该注解能使用在使用类型的任意语句中。

  • 创建实例时使用
User user1 = new @Annotation1 User();
  • 类型强转时使用
Object o = "1";
String s = (@Annotation1 String) o;
  • 方法形参时使用
public void Test(@Annotation1("方法参数上的注解") String s, @Annotation1("方法参数上的注解2") String s2){

    }
  • 泛型中使用
private Map<@Annotation1("成员变量泛型上的注解") String,String> map;

 参考:JAVA8新特性--类型注解与重复注解_凶猛的小蜜蜂-CSDN博客_type_use

@Documented

在声明注解时指定 @Documented,则它会被 javadoc 之类的工具处理, 注解类型信息也会被包括在生成的文档中。

@Inherited

JDK中定义注解不可继承,使用该注解可被继承

作用:让子类可以继承修饰父类的注解,前提是此注解已被@Inherited修饰。
@Inherited使得被其修饰的注解能够被继承。

扩展:在spring中也有一个@AliasFor注解可实现注解继承效果,不过得通过spring处理后才能实现功能

@Retention

注解的保留策略(枚举类RetentionPolicy),RetentionPolicy可选值:

SOURCE:注解仅存在于源码中,在class字节码文件中不包含
CLASS:默认的保留策略,注解在class字节码文件中存在,但运行时无法获得
RUNTIME:注解在class字节码文件中存在,在运行时可以通过反射获取到

二、自定义注解

jdk中和注解有关的类都定义在java.lang.annotation包中
注解的本质还是接口,注解继承了Annotation接口

注解使用@interface来定义
例如:定义一个TestAnnotation注解

public @interface TestAnnotation {
    int age() default 1;
}

注意:1.访问修饰符必须是public 不写默认public
           2.参数类型必须是基本数据类型、String、Class、枚举类型、注解类型以及上述类型的数组,像Integer、Double这些(包装类型)都不行。
           3.参数名字一般定义为名词,如果只有一个参数,一般定义为value。
  因为:只有一个参数,并且名称为value时,注解使用时可以省略参数名。
  即:

public @interface TestAnnotation {
    String value();
}

 这时可以直接写

@TestAnnotation("1")

           4.default设定参数默认值,使用注解时不指定参数,参数使用默认值。
           5.参数名称后面的()内不能添加任何东西,这只是个特殊的语法。
           6.如果没有默认值,使用注解时必须赋值

三、注解信息的获取

Java在 java.lang.reflect 反射包下增设了AnnotatedElement 接口

主要用于表示目前正在虚拟机中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术读取注解的信息

Package:用来表示包的信息
Class:用来表示类的信息
Constructor:用来表示构造方法信息
Field:用来表示类中属性信息
Method:用来表示方法信息
Parameter:用来表示方法参数信息

以上这些类实现了AnnotatedElement接口

@Target({ElementType.TYPE,
        ElementType.METHOD,
        ElementType.FIELD,
        ElementType.TYPE_USE,
        ElementType.PARAMETER,
        ElementType.CONSTRUCTOR})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Annotation1 {
    String value() default "";
}
@Annotation1("类上的注解")
public class TestAnnotation <@Annotation1("类变量类型(泛型)上的注解") T0,T1>{
    @Annotation1("成员变量上的注解")
    private Map<@Annotation1("成员变量泛型上的注解") String,String> map;

    @Annotation1("成员方法上的注解")
    public void Test(@Annotation1("方法参数上的注解") String s, @Annotation1("方法参数上的注解2") String s2){

    }

    @Annotation1("构造函数上的注解")
    public TestAnnotation(){

    }
}
@Test
    public void test12() throws NoSuchFieldException, NoSuchMethodException {
        Class<TestAnnotation> clazz = TestAnnotation.class;
        //获取类上的注解
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println(annotation);
        }
        //是否存在注解
        /*if(clazz.isAnnotationPresent(Annotation1.class)){
            Annotation1 annotation1 = clazz.getAnnotation(Annotation1.class);
            System.out.println(annotation1.value());
        }*/

        //获取类的类型变量(泛型)的注解
        TypeVariable<Class<TestAnnotation>>[] typeParameters = clazz.getTypeParameters();
        for(TypeVariable typeVariable : typeParameters){
            System.out.println(typeVariable.getName());
            Annotation[] annotations1 = typeVariable.getAnnotations();
            for (Annotation annotation : annotations1) {
                System.out.println(annotation);
            }
        }

        //获取成员变量上的注解
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
            for (Annotation annotation : field.getAnnotations()) {
                System.out.println(annotation);
            }
        }

        //获取成员变量泛型的注解
        for (Field field : fields) {
            AnnotatedParameterizedType annotatedType = (AnnotatedParameterizedType) field.getAnnotatedType();
            AnnotatedType[] typeArguments = annotatedType.getAnnotatedActualTypeArguments();
            for (AnnotatedType typeArgument : typeArguments) {
                for (Annotation annotation : typeArgument.getAnnotations()) {
                    System.out.println(annotation);
                }
            }
        }

        //获取成员方法上的注解
        Method test = clazz.getMethod("Test", String.class, String.class);
        for (Annotation annotation : test.getAnnotations()) {
            System.out.println(annotation);
        }

        //获取成员方法上的参数注解
        for (Parameter parameter : test.getParameters()) {
            for (Annotation annotation : parameter.getAnnotations()) {
                System.out.println(annotation);
            }
        }

        //获取构造函数上的注解
        Constructor<TestAnnotation> constructor = clazz.getConstructor();
        for (Annotation annotation : constructor.getAnnotations()) {
            System.out.println(annotation);
        }

    }

参考地址:JAVA核心知识点--元注解详解_pengjunlee的博客-CSDN博客_元注解

java学习-自定义注解,使用注解,注解的信息获取,注解继承_whatname123的博客-CSDN博客_自定义注解继承

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值