Java注解

Java注解

0.参考

Java 注解完全解析

Java获取类方法上的注解

1.注解的定义

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestAnnotation {
    String type() default "";
}

2.元注解

元注解顾名思义我们可以理解为注解的注解,它是作用在注解中,方便我们使用注解实现想要的功能。它是Java提供的用来定义其他注解的注解。元注解分别有@Retention、 @Target、 @Document、 @Inherited和@Repeatable(JDK1.8加入)五种。

2.1 @Retention

Retention英文意思有保留、保持的意思,它表示注解存在阶段是保留在源码(编译期),字节码(类加载)或者运行期(JVM中运行)。在@Retention注解中使用枚举RetentionPolicy来表示注解保留时期。

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

​ 如果我们是自定义注解,则通过前面分析,我们自定义注解如果只存着源码中或者字节码文件中就无法发挥作用,而在运行期间能获取到注解才能实现我们目的,所以自定义注解中肯定是使用 @Retention(RetentionPolicy.RUNTIME)

@Retention(RetentionPolicy.RUNTIME)     //运行时可检测到
public @interface TestAnnotation {
    
}

2.2 @Target

Target的英文意思是目标,这也很容易理解,使用@Target元注解表示我们的注解作用的范围就比较具体了,可以是类,方法,方法参数变量等,同样也是通过枚举类ElementType表达作用类型

  • @Target(ElementType.TYPE) 作用接口、类、枚举、注解
  • @Target(ElementType.FIELD) 作用属性字段、枚举的常量
  • @Target(ElementType.METHOD) 作用方
  • @Target(ElementType.PARAMETER) 作用方法参数
  • @Target(ElementType.CONSTRUCTOR) 作用构造函数
  • @Target(ElementType.LOCAL_VARIABLE)作用局部变量
  • @Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)
  • @Target(ElementType.PACKAGE) 作用于包
  • @Target(ElementType.TYPE_PARAMETER) 作用于类型泛型,即泛型方法、泛型类、泛型接口
  • @Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class

一般比较常用的是ElementType.TYPE类型

2.3 @Documented

Document的英文意思是文档。它的作用是能够将注解中的元素包含到 Javadoc 中去。

2.4 @Inherited

Inherited的英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,则它的子类也继承了父类的注解。

//自定义注解
@Inherited
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    String type() default "";
}

//父类
@TestAnnotation(type = "animal")
public class Animal {
}
//子类
public class Panda extends Animal{
    public String name = "panda";
}

//控制台运行
public class Console {
    public static void main(String[] args) {
        //获取所有注解
        Annotation[] annotations = Panda.class.getAnnotations();
        for (int i = 0; i < annotations.length; i++) {
            //打印输出子类的注解
            System.out.println(annotations[i].toString());
        }
    }
}

结果

image

2.5 @Repeatable

Repeatable的英文意思是可重复的。顾名思义说明被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。

//容器注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Fruits {
    Apple[] value() ;
}

//具体注解
@Repeatable(value = Fruits.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Apple {
    double price();
}
//被注解类
@Apple(price = 2.0)
@Apple(price = 3.0)
public class Businessman {
}

//运行
public class Console {
    public static void main(String[] args) {
        Annotation[] annotations = Businessman.class.getAnnotations();
        Fruits fruits = (Fruits)annotations[0];
        for (Apple a:fruits.value()) {
            System.out.println("价格="+a.price());
        }
    }
}

//结果
价格=2.0
价格=3.0

注:

  • @Repeatable必须用两个注解来搭配使用
  • 容器注解必须定义一个具体注解的属性,属性名必须是value。相当于把具体注解保存到容器注解的value数组中

3.注解的属性

注解的属性其实和类中定义的变量有异曲同工之处,只是注解中的变量都是成员变量(属性),并且注解中是没有方法的,只有成员变量,变量名就是使用注解括号中对应的参数名,变量返回值就是注解括号中对应参数值。可使用defalue来定义默认值

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    @AliasFor(annotation = Component.class)
    String value() default "";

}

4.注解的本质

注解的本质就是一个Annotation接口

/**Annotation接口源码*/
public interface Annotation {

    boolean equals(Object obj);
    
    int hashCode();

    Class<? extends Annotation> annotationType();
}

5.注解使用时的常用方法

  • Class.getAnnotations() 获取所有的注解,包括自己声明的以及继承的
  • Class.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的
  • Class.getDeclaredAnnotations() 获取自己声明的注解
  • Class.isAnnotationPresent(Class< A > annotationClass) 判断是否有某个注解

方法,属性,构造器,类都可以使用上面的方法。

public class Console {
    public static void main(@RequestParam String[] args) throws NoSuchFieldException, NoSuchMethodException {
        System.out.print("获取类上面的所有注解:");
        Annotation[] annotations = Businessman.class.getAnnotations();
        for (int i = 0; i < annotations.length; i++) {
            System.out.println(annotations[i].annotationType());
        }

        Class<Businessman> clazz = Businessman.class;
        System.out.println("判断类上的是否注解:"+clazz.isAnnotationPresent(Apple.class));

        Field name = clazz.getField("Name");
        System.out.println("判断属性上的是否注解:"+name.isAnnotationPresent(Fruits.class));

        Method sell = clazz.getMethod("sell");
        System.out.println("判断方法上的是否注解:"+sell.isAnnotationPresent(Fruits.class));

        boolean hasAnnotation = clazz.isAnnotationPresent(Apple.class);
        if(hasAnnotation){
            Apple annotation = clazz.getAnnotation(Apple.class);
            System.out.println("注解上面的值:"+annotation.price());
        }
    }
}
//输出 
获取类上面的所有注解:interface com.meng.daily.basejava.annotation.Apple
判断类上的是否注解:true
判断属性上的是否注解:false
判断方法上的是否注解:false
注解上面的值2.0

在spring中可以使用AnnotationUtils工具类来进行操作

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

推荐阅读更多精彩内容