Java注解知识梳理--注解概念知识

Java注解

注解是JDK5引入的一个特性,可以为我们的代码打上一个标记,配合java中的反射会有意想不到的惊喜。我们经常用到很多框架都是用到了该特性。所有的注解都继承于Annotation。

Java 8以前,注解只能在声明的地方使用(声明方法、变量、类等),Java 8开始,注解可以在任何地方使用(泛型、抛异常、方法中等),这是因为Java 8 增加了两种ElementType(下文会介绍)。

  • 备注:代码基于Android API 26 中的java代码以及Java 8中的代码(Mac>>Android studio 3.3.2)。

注解的示例

  • 自定义注解代码示例:
/**
 * 测试注解
 * TestApplication
 * Created by anonyper on 2019/5/30.
 */
@Retention(RetentionPolicy.RUNTIME)//属于运行时注解
@Target(ElementType.METHOD)//适用于方法注解
public @interface TestAnnotationMethod {
    
    String LabelType() default "default";//注解中LabelType 取值
}
  • 系统内置注解代码示例:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
  • 使用代码示例:
public class RachelApplication extends Application {
    //系统注解
    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this, LocationService.class);
        startService(intent);
    }

    //自定义注解
    @TestAnnotationMethod(LabelType = "Wifi")
    public void testMethod() {

    }
}

注解基本语法介绍

从示例中可以看到,使用@interface即可标示这是一个注解,一个注解包括元注解注解属性两部分。下面我们分别来介绍元注解、Java内置的常用注解以及注解属性

注解属性

注解起到一种标记作用,有的时候我们需要给定不同的属性,比如上面的String LabelType() default "default";//注解中LabelType 取值这段代码。这是用来给一个注解指定一个属性。比如我们用到的@Target注解,里面的值是一个枚举,代表着该注解的不用使用范围。再比如,我们自定义一个注解用于标示人物身份,那么身份的值就可能包含:老师、学生、企业家、律师、医生等等。

注解的属性也可以叫做成员变量(注解内不能有方法的),定义属性的时候需要用无形参的方式来声明,并且方法名代表变量名字,返回值代表属性的类型(属性类型可为:8种基本类型(byte字节型、short短正型、int整型、long长整型、float单精度浮点型、double双精度浮点型、boolean布尔型、char字符型)、Class类型、String、枚举、注解以及他们的数组)。

  • 属性的使用:
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//适用于方法注解
public @interface TestAnnotation {

    String LabelType() default "guanwang" ;
}

//使用:
@TestAnnotation(LabelType = "Wifi")
public class RachelApplication{
  
}

//或者
@TestAnnotation//默认是guanwang
public class RachelApplication{
  
}

//或者
@TestAnnotation()//默认是guanwang
public class RachelApplication{
  
}
  • value

value算是一个特殊的属性,如果一个注解中只有value属性需要设置(没有其他属性或其他属性有默认值),在设置时value=可以省略。

@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//适用于方法注解
public @interface TestAnnotation {

    String LabelType() default "guanwang" ;
    String value();
}
//使用
@TestAnnotation("GPRS")
public class RachelApplication{
  
}
  • 其他类型属性
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//适用于方法注解
public @interface TestAnnotation {

    int index() default 1;//int 类型

    boolean flag() default false;//布尔类型

    String LabelType() default "guanwang";//字符串

    int[] arrayint() default {1, 2, 3, 4};//数组

    ElementType elementType() default ElementType.TYPE;//枚举类型 用了ElementType做示例

    Target target() default @Target(ElementType.TYPE); //注解类型 这里用了Target做示例

    Class<?> classType() default Integer.class;//class类型
  
    String value();
}

元注解

元注解就是可以标记注解的注解,我们在声明注解使用的范围@Target,生存周期@Retention等我们常用的,还有一些诸如@Documented、@Inherited、@Repeatable等元注解,我们接下来一一说明他们各自的含义:

@Target

限定注解的作用范围,比如方法、类、变量、等,具体如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Target {
    ElementType[] value();
}

//ElementType 代码如下
public enum ElementType {
    ANNOTATION_TYPE,//可以用在另一个注解上(自定义元注解)
    CONSTRUCTOR,//可以用于构造方法上
    FIELD,//可以用于字段声明上,包括枚举上
    LOCAL_VARIABLE,//可以用于局部变量上
    METHOD,//可以用于方法上
    PACKAGE,//可以用于包声明上
    PARAMETER,//可以用于参数声明上
    TYPE,//可以用于类、接口、枚举声明上
    TYPE_PARAMETER,//表示注解能写在类型变量的声明语句中。1.8版本加入的 网上的示例比如
    //List<Integer> list = new @Save ArrayList<>(); 但是我在测试过程中报错(Mac AndroidStudio 3.3.2 Android 26 java 1.8 ),唯一测试可用的地方:public class Book<@TestAnnotation T>
    TYPE_USE;//表示注解能写在使用类型的任何语句中 1.8版本加入 如
    /**
        public class Book<@TestAnnotation T> {
            List<Integer> list = new @TestAnnotation ArrayList<>();
            @TestAnnotation int index = 10;//默认10本书
            public @TestAnnotation int getIndex() {
            return 1;
            }
        }
    */

    private ElementType() {
    }
}

Java 8 新增的两个类型注解的作用是用来强健java代码,配合第三方工具(如Checker Framework)做强类型检查,可以在编译期检测出异常(如UnsupportedOperationException、NullPointerException异常等),避免了程序在运行时才抛出错误,这就是类型注解的主要作用。

@Retention

用来标示该注解的生存周期,比如运行时注解、编译时注解等。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Retention {
    RetentionPolicy value();
}

//RetentionPolicy 代码如下
public enum RetentionPolicy {
    CLASS,//标示注解只被保留到编译的时候,不会被加载到JVM中
    RUNTIME,//标示注解可以保留到运行时,会被加载到JVM中
    SOURCE;//标示注解只是在源代码阶段,在编译前会被忽略

    private RetentionPolicy() {
    }
}

@Documented

标示将注解的元素包含到javadoc中。(我们可以把我们的代码生成API文档的哦)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Documented {
}

@Inherited

标示改注解可以被继承,如果一个父类使用该注解,子类没有做其他注解时,默认继承了父类的注解。

@Inherited //该注解可以被继承
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Target(ElementType.TYPE)//适用于类注解
public @interface TestAnnotationType {
}

//父类使用注解,该注解有Inherited标示
@TestAnnotationType
class ParentClass {

}

//子类默认继承父类的注解
public class ChildClass extends ParentClass {

}

@Repeatable(Java 8增加的)

标示该注解在一个地方可重复使用,可以取不同的值,如一个人的身份可以是律师,他还兼职老师的工作。需要传入一个继承注解的类来作为其容器。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Repeatable {
    Class<? extends Annotation> value();
}

//使用方法:

//注解容器
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Identitys {
    Identity[] value();//必须有一个方法名为 value 返回的类型用的是使用Repeatable的注解
}

//声明可重复
@Repeatable(Identitys.class)//容器类是Identitys
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Identity {
    String label();
}

//具体使用
@Identity(label = "student")
@Identity(label = "teacher")
public class TestRepeatable {

}

Java内置常用注解

我们在继承一个类,子类重新父类方法时是不是用到@Override,在看到老版本废弃的方法时,是否看到@Deprecated呢,这些都是Java内置的注解,常用的有:

@Override

标示子类复写了父类的方法用到的修饰。防止父类方法名改变时,子类方法忘记做对应调整。

@Deprecated

标示过时的元素,虽然可以调用,但不建议使用的意思,使用的时候,在IDE上会显示一条灰色的线。

@SuppressWarnings

阻止编译器对被标记方法、类发出警告,里面需要传入阻止警告的哪些类型,常用的:all(所有警告)、unchecked(没有进行类型检查操作的警告)、unused(没有使用过的代码警告),deprecation(使用过期方法)。所以在调用过时方法的方法前面加上@SuppressWarnings("deprecation"),那条灰色就不会显示了。

具体SuppressWarnings类型值的解释,可以自行百度。

@SafeVarargs (Java 7新增)

Java SE 5中引入的可变形参加上Java编译器的机制,导致在使用可变形参的时候,编译器会产生一个未经检查的警告,SafeVarargs注解就可以忽略这些警告。SafeVarargs注解只能用在参数长度可变的静态方法(或用final修饰)或构造方法上,否则会出现编译错误。(这些只是屏蔽了编译时的警告,如果类型转化错误,在运行时还会报错的)。

SafeVarargs产生由来介绍

@FunctionalInterface(Java 8新增)

该注解标示该类是一个函数式的接口,就是里面除了Object类中public修饰的方法外只有一个抽象方法。比如 View.OncClickListener,Runnable等都可以使用FunctionalInterface标记一下。这些函数式接口可以使用lambda表达式来编写。

注解的使用

上面介绍了注解的基本知识,我们学会了如何对一个元素用注解进行标记,那么接下来我们就要考虑标记之后如何识别呢?这些内容因为篇幅原因,我们就另开一篇分析。

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

推荐阅读更多精彩内容