Java基础之注解Annotation

Java之注解.png

Java 注解用于为 Java 代码提供元数据。作为元数据,注解并不会直接影响你的代码执行。

1. 注解的定义

注解的定义与类的定义有些类似,只是将class换成@interfacexiu即可

public @interface AnnoTest {
    
}

但仅仅被@interface修饰还不够,一个完整的自定义注解还需要配合元注解使用。所以还先需要了解元注解是什么?怎么使用?

2. 注解分类

  • JDK自带注解:@Override、@Deprecated、@SuppressWarning
  • 元注解:@Target、@Retention、@Inherited、@Documented
  • 自定义注解
2.1 JDK自带注解
  • @Override:表示为被重写的方法
  • @Deprecated:表示过时的方法
  • @SuppressWarning:表示忽略警告
2.2 元注解

用来标记注解的注解

  • @Target

表示注解的作用域,通过枚举类ElementType表达作用类型,可以是类,方法,方法参数变量等。

其中枚举类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, // 作用于注解(@Retention注解中就使用该属性)

    /** Package declaration */
    PACKAGE, // 作用于包

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER, // 作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)

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

表示注解存在的生命周期。注解存在阶段是保留在源码(编译期),字节码(类加载)或者运行期(JVM中运行)。通过枚举类RetentionPolicy来表示注解保留时期。

其中枚举类RetentionPolicy的取值如下:

public enum RetentionPolicy {
    /**
     * 注解只存在源码中,编译时会丢弃
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * 注解会在class字节码文件中存在,在运行时可以通过反射获取到
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
  • @Documented

它的作用是能够将注解中的元素包含到 Javadoc 中去。

  • @Inherited

一个被@Inherited注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。

2.3 自定义注解(后面讲解)

3. 注解的作用

  • 标记,用于告诉编译器的一些信息
  • 编译时动态处理,如动态生成代码
  • 运行时动态处理,如得到注解信息

4. 自定义注解并解析注解

4.1 自定义注解
  • 使用@interface关键字定义注解
  • 成员以无参无异常的方式声明
  • 可以用default为成员指定默认值
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AnnoTest {  // 使用@interface关键字定义注解
    //成员以无参无异常的方式声明
    String desc();
    String author();
    
    //可以用default为成员指定默认值
    int age() default 18;
}
4.2 注解的属性类型
  • 基本数据类型
  • String类型
  • 枚举类型
  • 注解类型
  • Class类型
  • 以上类型的数组类型
4.3 使用注解

注解属性赋值:如果注解有多个属性,则可以在注解括号中用“,”号隔开分别给对应的属性赋值

@AnnoTest(desc="annotation class desc", author="annotation class author",age=20)
public class AnnoTestDemo {

    @AnnoTest(desc="annotation method desc", author="annotation method author",age=30)
    public String test() {
        return "test";
    }
}
4.4 解析注解

注:如果我们在定义自己的注解的时候,将@Retention(RetentionPolicy.RUNTIME)改为@Retention(RetentionPolicy.SOURCE)或者@Retention(RetentionPolicy.CLASS),运行上面的程序是不会出现任何结果,因为只有运行时注解可以通过反射获取,其他两种注解在运行时已经被丢弃了。

public static void main(String[] args) {
    try {
        //1、使用类加载器加载类
        Class<?> c = Class.forName("com.anno.AnnoTestDemo");
        //2、找到类上面的注解
        //先判断AnnTestDemo类上面有没有AnnoTest这样的注解
        boolean isExist = c.isAnnotationPresent(AnnoTest.class);
        if (isExist) {
            //3、获取类上的注解实例
            AnnoTest classAnno = (AnnoTest) c.getAnnotation(AnnoTest.class);
            System.out.println(classAnno.author());
        }

        //4、找到方法上的注解
        //拿到给定类所包含的方法
        Method[] methods = c.getDeclaredMethods();
        //遍历方法
        for (Method method : methods) {
            boolean isMExist = method.isAnnotationPresent(AnnoTest.class);
            if (isMExist) {
                //拿到每个方法上的注解
                AnnoTest methodAnno = method.getAnnotation(AnnoTest.class);
                System.out.println(methodAnno.author());
            }
        }

        //另外一种解析方法上注解的方式
        //遍历所有的方法
        for (Method method : methods) {
            //拿到每个方法上的注解
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof AnnoTest) {
                    AnnoTest methodAnno = (AnnoTest) annotation;
                    System.out.println(methodAnno.author());
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5. 参考

https://www.jianshu.com/p/9471d6bcf4cf

公共技术点之 Java 注解 Annotation

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355