前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【刨根问底】java注解--下

【刨根问底】java注解--下

作者头像
田维常
发布2019-07-16 11:01:49
2840
发布2019-07-16 11:01:49
举报
文章被收录于专栏:Java后端技术栈cwnait

1

JDK元注解

@Retention

@Retention只能修饰注解定义,用于指定被修饰的注解可以保留多长时间,@Retention包含了一个RetentionPolicy类的value变量,所以使用此注解时必须为该value变量赋值。源码如下:

代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}
代码语言:javascript
复制
public enum RetentionPolicy {
    // 注解之保留在源代码中,编译器直接丢弃这种注解
    SOURCE,
    // 编译器将把注解记录仪在class文件中,当运行java程序时,
    //JVM不可获取注解信息,---默认值
    CLASS,
    //编译器将把注解记录在class文件中,当运行java程序时,
    //JVM也可以获取注解信息,程序代码里也可以通过反射获取注解信息
    RUNTIME
}

两种使用方式:

代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRetentionAnnotation {
}
代码语言:javascript
复制
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyRetentionAnnotation {
}

提示

如果使用注解时只需要为value成员变量指定值,则使用该注解时可以直接在该注解后的括号里指定value的值,无须使用value=值的形式。

@Target

@Target也是只能修饰注解定义,他用于指定被修饰的注解能用于修饰哪些程序单元,@Target元注解也包括一个value的变量。看源码:

代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

@Target中的value变量对应的是一个枚举ElementType;

代码语言:javascript
复制
public enum ElementType {
    //指定该策略的注解可以修饰类、接口(包括注解类型)或枚举定义
    TYPE,
    //指定该策略的注解只能修饰成员变量的定义
    FIELD,
    //指定该测录的注解只能修饰方法的定义
    METHOD,
    //指定该策略的注解可以修饰参数
    PARAMETER,
     //指定该策略的注解只能修饰构造器
    CONSTRUCTOR,
    //指定该策略的注解只能修饰局部变量
    LOCAL_VARIABLE,
    //指定该策略的注解只能修饰注解
    ANNOTATION_TYPE,
    //指定该策略的注解只能修饰包定义
    PACKAGE,
    //JDK1.8版本开始
    //指定该策略的注解只能修饰参数类型的定义
    TYPE_PARAMETER,
    //JDK1.8版本开始
    //指定该策略的注解只能修饰一个类型的使用
    TYPE_USE
}

定义方式和@Retention一样。

@Documented

@Ducumented用于指定被该元注解修饰的注解将被javadoc工具提取成文档,如果定义注解类时使用了@Documented修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。其源码:

代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

案例:

代码语言:javascript
复制
@Documented
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyRetentionAnnotation {
//自定义注解 加上注解Documented
}
代码语言:javascript
复制
public class MyTest {
    //使用自定义注解
    @MyRetentionAnnotation
    public String annotation() {
        return super.toString();
    }
}

找到当前类路径,然后执行:

javadoc -d doc MyTest.java

打开index.html

进入MyTest

ok,文档已经生成,这个注解的作用也就体现出来了。

@Inherited

@Inherited元注解指定被他修饰的注解将具有继承性,如果某个类使用了@Xxx注解同事@Xxx注解上有@Inherited修饰,则其子类将自动被@Xxx修饰。

案例:

代码语言:javascript
复制
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyInherited {
//自定义注解
}

把自定义注解注解于父类上,

代码语言:javascript
复制
@MyInherited
public class BaseInherited {
}
代码语言:javascript
复制
//子类继承父类
public class InheritedDemo extends BaseInherited {
    public static void main(String[] args) {
        //InheritedDemo上是否有注解Inherited
    System.out.println(
    InheritedDemo.class.isAnnotationPresent(MyInherited.class));
    }
}

运行结果:true。证明子类继承了父类的@MyInherited。

2

自定义注解

定义注解

文章前面部分已经写过好几次自定义注解了。还是继续说说,首先是注解的定义:只要在接口中的interface前面加一个@就变成注解了。表达不是很完美。请看下面:

代码语言:javascript
复制
//定义一个简单的注解
public @interface MyAnnotation {
}

注解通常放在所有修饰符之前,使用:

代码语言:javascript
复制
public class MyTest {
    @MyAnnotation
    public String annotation() {
        return "Java后端技术栈";
    }
}
代码语言:javascript
复制
@MyAnnotation
public class MyTest {
    public String annotation() {
        return super.toString();
    }
}

根据注解是否可以包含成员变量、可以把注解分为如下两类:

1:标记注解,没有定义成员变量@override和@MyAnnotation等注解。

2:元素注解,包含成员变量的注解,因为他们可以接受更多的元素据,所以也被称之为元数据注解

提取注解

使用反射获取注解相关信息,在java.lang.Class中有几个方法跟注解有关系:

下面来一个使用案例

先自定义一个注解:

代码语言:javascript
复制
/**
 * 自定义注解
 * @author lawt
 * @date 2019/6/28
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
    String value() default "";
}
代码语言:javascript
复制
/**
 * @author lawt
 * @date 2019/6/28
 */
@MyAnnotation(value = "Java后端技术栈")
public class MyMyAnnotationDemo {
    public static void main(String[] args) {
        boolean hasMyAnnotation = MyMyAnnotationDemo.class.isAnnotationPresent(MyAnnotation.class);
        if (hasMyAnnotation) {
            MyAnnotation myAnnotation = MyMyAnnotationDemo.class.getAnnotation(MyAnnotation.class);
            System.out.println(myAnnotation.value());
        }
    }
}

输出

ok,自此提取注解结束,提取注解的其他方法请自行试试。我们在工作中一般无非就是使用到自定义注解和提取注解是使用最频繁之一。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档