注解基础知识

一、概要

  • 注解对于开发人员来讲既熟悉又陌生
  • Java注解又称为标注,是Java从1.5开始支持加入源码的特殊语法元数据;
  • 对修饰的元素进行解释说明

二、应用场景

  • 动态配置信息
  • 配合反射实现程序逻辑
  • 代码格式检查,比如Override、Deprecated、NonNull等,便于IDE能够检查出代码错误

三 常见内置注解(了解)

1、@Override

标记注解,不需要设置属性值;只能添加在方法的前面,用于标记该方法是复写的父类中的某个方法,如果在父类没有的方法前面加上@Override注解,编译器会报错

2、 @Deprecated

标记注解,不需要设置属性值;作用是标记当前的类或者方法或者字段等已经不再被推荐使用了,可能在未来的版本中会删除

3、@SuppressWarnings

可以对构造方法、变量、方法、包、参数标记,用于告知编译器忽略指定的警告,不用再编译完成后出现警告信息

4、 @Nullable

用于标记方法参数或者返回值可以为空;

5、@NonNull

用于标记方法参数或者返回值不能为空,如果为空编译器会报警告;

四、自定义注解(重点)

1、说明

注解跟 class, interface,enum一样,注解也属于一种类型。

2 、语法格式

  1. 格式

     public @interface 注解名 {定义体}
    
  2. 说明

    他定义的形式跟接口很类似,不过前面多了一个 @ 符号。

  3. 举个栗子

    public @interface TestAnnotation {
    }
    

3 、注解的应用

  1. 说明

    注解可以用在类,接口 枚举等任何地方

  2. 举个栗子

    @TestAnnotation
    public class User {
      @TestAnnotation
      private String name;
      @TestAnnotation
     public void setName(@TestAnnotation name){
      }
    }
    
    @TestAnnotation
    public enum Color {
    }
    
    @TestAnnotation
    public interface TestService {
    }
    

4、注解的属性

  1. 说明

    注解的属性也叫做成员变量。注解只有成员变量,没有方法。

    注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。

  2. 语法格式

    public @interface TestAnnotation {
      类型 变量() default 默认值; 
    }
    
  3. 类型可选值

    • 基本类型(int,float,boolean,byte,double,char,long,short)
    • String类型
    • Class类型
    • enum类型
    • Annotation类型
    • 以上所有类型的数组
  4. 例如

    public @interface TestAnnotationField {
      String value() 
     int id() default "0";
     String hello() default "";
      Stirng[] detail();
    }
    /*
     * 1. 只能用public或默认(default)这两个访问权修饰.例如,String value()
     * 2. 可以设置defaul值 如果设置了default值,在使用的时候可以省略不写
     */
    
  5. 使用

    // 赋值的方式是在注解的括号内以 value="" 形式,多个属性之前用 ,隔开。
    @TestAnnotationField(value='test', id=1, hello="坤坤", detail=['1','2','3'])
    public class User {
    }
    
  6. 注意如果属性的名称是value时可以省略

    public @interface TestAnnoValue {
      String value() 
    }
    @TestAnnoValue("value可以省不写")
    public class User {
    }
    

五、元注解

用于修饰注解的注解叫元注解,内置的元注解

@Retention、@Documented、@Target、@Inherited、@Repeatable(jdk1.8新增)5 种。

1、@Retention(重点)

  1. 作用

    表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

  2. 语法格式

    public @interface Retention {
        RetentionPolicy value();
    }
    
  3. 可选值

    可选值 说明
    RetentionPolicy.SOURCE 在源文件中有效(即源文件保留)
    RetentionPolicy.CLASS 在class文件中有效(即class保留)
    RetentionPolicy.RUNTIME 在运行时有效(即运行时保留)
  4. 举个栗子

    @Retention(RetentionPolicy.SOURCE)
    public @interface RetentionDemo {
    }
    

2、@Target(重点)

  1. 作用

    Target 是目标的意思,@Target 指定了注解可以修饰那些元素,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

  2. 语法格式

    public @interface Target {
        ElementType[] value();
    }
    
  3. 可选值

    类型 说明
    ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
    ElementType.CONSTRUCTOR 可以给构造方法进行注解
    ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
    ElementType.FIELD 可以给属性进行注解
    ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
    ElementType.METHOD 可以给方法进行注解
    ElementType.PACKAGE 可以给一个包进行注解
    ElementType.PARAMETER 可以给一个方法内的参数进行注解
    ElementType.TYPE_USE 可以用于标注任意类型

3、@Inherited(掌握)

  1. 作用

    使用此注解声明出来的自定义注解,在使用此自定义注解时,

  2. 注意事项

    如果注解在类上面时,子类会自动继承此注解,否则的话,子类不会继承此注解。也就是说使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效

  3. 语法格式

    public @interface Inherited {
    }
    
  4. 举个栗子

    /**
     * 没有使用Inherited元注解,表示此注解用在类上时,不会被子类所继承
     * @author zhangwei
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    public @interface NoInheritedAnnotation {
        String value();
    }
    
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface InheritedAnnotation {
        String value();
    }
    
    
    @InheritedAnnotation("使用Inherited的注解class")
    @NoInheritedAnnotation("未使用Inherited的注解class")
    public class Parent {
        @InheritedAnnotation("使用Inherited的注解 field")
        @NoInheritedAnnotation("未使用Inherited的注解field")
        public String name;
        @InheritedAnnotation("使用Inherited的注解 method")
        @NoInheritedAnnotation("未使用Inherited的注解 method")
        public String getName() {
            return name;
        }
    }
    

4、@Repeatable

  1. 作用

    java8 新增的,允许在同一修饰的类型(类,属性,或方法)的多次使用同一个注解

  2. 举个栗子

    // jdk8 之前
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Annotation8 {
        String [] value();
    }
    //使用
    @Annotation8({"/update","/add"})
    public class TestAnno{
    }
    
    
    /*
     * 1. 定义需要重复的注解
     * 3.在需要重复使用的注解上的值指向容器的.class
     */
    @Repeatable(RepeatableContainer.class)
    public @interface RepeatableAnnotation {
         String value();
    }
    
    /*
     * 2.定义个一容器注解
     */
    public @interface RepeatableContainer {
        RepeatableAnnotation[] value();
    }
    // 测试
    public class RepeatTest {
        @RepeatableAnnotation("1")
        @RepeatableAnnotation("2")
        public void toDo() {
        }
    }
    

5、@Documented(了解)

  1. 作用

    用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

七、注解与反射

1、说明

在以下的类中Class Constructor Field Method Package等类都实现了AnnotatedElement接口相关API

同时配合反射提供的api我们就可以在程序运行时(@Retention(RetentionPolicy.RUNTIME))拿到注解

2、注解相关api

方法 说明
getDeclaredAnnotations() 获取声明过的所有Annotation
getAnnotations() 获取所有的Annotation
isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断annotation是否存在
getAnnotations(Class annotationType) 获取一个指定的annotation类型

3、举个栗子

  1. 综合栗子

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FieldAnnotation {
        String name();
        int id() default 0;
    }
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MethodAnnotation {
        String value();
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    public @interface TypeAnnotation {
        String value();
        int id() default 0;
    }
    
    @TypeAnnotation(value = "注解在类上使用", id = 1)
    public class TestBean {
        @FieldAnnotation(name = "注解在变量上使用")
        private String name;
    
        @MethodAnnotation(value = "在方法上使用")
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    
  2. 注解继承

    @Inherited
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ParentAnnotation {
        String id();
    }
    
    

4、封装ORM

  1. 属性

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

推荐阅读更多精彩内容

  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和...
    九尾喵的薛定谔阅读 3,152评论 0 2
  • 备注: 本文大部分内容及代码均来自网上,具体引用看末尾 8.参考引用** 概念及作用 JDK注解 元注解 自定...
    ting723阅读 1,483评论 2 5
  • 理解 注解就是标签 这里先不引出概念 具体描述 注解是在JavaSE 5.0版本引入的一个概念 注解的定义 使用@...
    dashingqi阅读 208评论 0 0
  • 反射 一、概要 注解对于开发人员来讲既熟悉又陌生,熟悉是因为只要你是做开发,Java注解又称为标注,是Java从1...
    唯老阅读 318评论 0 0
  • 关于注解首先引入官方文档的一句话:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代...
    编程小世界阅读 456评论 0 0