@Retention注解作用

2023-11-12

@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.

从注释上看:

source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略

class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期

runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。


那怎么来选择合适的注解生命周期呢?

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife,就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解

下面来介绍下运行时注解的简单运用。

获取注解

你需要通过反射来获取运行时注解,可以从 Package、Class、Field、Method...上面获取,基本方法都一样,几个常见的方法如下:

  1. /**
  2. * 获取指定类型的注解
  3. */
  4. public <A extends Annotation> A getAnnotation(Class<A> annotationType);
  5. /**
  6. * 获取所有注解,如果有的话
  7. */
  8. public Annotation[] getAnnotations();
  9. /**
  10. * 获取所有注解,忽略继承的注解
  11. */
  12. public Annotation[] getDeclaredAnnotations();
  13. /**
  14. * 指定注解是否存在该元素上,如果有则返回true,否则false
  15. */
  16. public boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
  17. /**
  18. * 获取Method中参数的所有注解
  19. */
  20. public Annotation[][] getParameterAnnotations();

要使用这些函数必须先通过反射获取到对应的元素:Class、Field、Method 等。

自定义注解

来看下自定义注解的简单使用方式,这里先定义3个运行时注解:

  1. // 适用类、接口(包括注解类型)或枚举
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. public @interface ClassInfo {
  5. String value();
  6. }
  7. // 适用field属性,也包括enum常量
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target(ElementType.FIELD)
  10. public @interface FieldInfo {
  11. int[] value();
  12. }
  13. // 适用方法
  14. @Retention(RetentionPolicy.RUNTIME)
  15. @Target(ElementType.METHOD)
  16. public @interface MethodInfo {
  17. String name() default "long";
  18. String data();
  19. int age() default 27;
  20. }
这3个注解分别适用于不同的元素,并都带有不同的属性,在使用注解是需要设置这些属性值。

再定义一个测试类来使用这些注解:

  1. /**
  2. * 测试运行时注解
  3. */
  4. @ClassInfo( "Test Class")
  5. public class TestRuntimeAnnotation {
  6. @FieldInfo(value = { 1, 2})
  7. public String fieldInfo = "FiledInfo";
  8. @FieldInfo(value = { 10086})
  9. public int i = 100;
  10. @MethodInfo(name = "BlueBird", data = "Big")
  11. public static String getMethodInfo() {
  12. return TestRuntimeAnnotation.class.getSimpleName();
  13. }
  14. }

使用还是很简单的,最后来看怎么在代码中获取注解信息:

  1. /**
  2. * 测试运行时注解
  3. */
  4. private void _testRuntimeAnnotation() {
  5. StringBuffer sb = new StringBuffer();
  6. Class<?> cls = TestRuntimeAnnotation.class;
  7. Constructor<?>[] constructors = cls.getConstructors();
  8. // 获取指定类型的注解
  9. sb.append( "Class注解:").append( "\n");
  10. ClassInfo classInfo = cls.getAnnotation(ClassInfo.class);
  11. if (classInfo != null) {
  12. sb.append(Modifier.toString(cls.getModifiers())).append( " ")
  13. .append(cls.getSimpleName()).append( "\n");
  14. sb.append( "注解值: ").append(classInfo.value()).append( "\n\n");
  15. }
  16. sb.append( "Field注解:").append( "\n");
  17. Field[] fields = cls.getDeclaredFields();
  18. for (Field field : fields) {
  19. FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
  20. if (fieldInfo != null) {
  21. sb.append(Modifier.toString(field.getModifiers())).append( " ")
  22. .append(field.getType().getSimpleName()).append( " ")
  23. .append(field.getName()).append( "\n");
  24. sb.append( "注解值: ").append(Arrays.toString(fieldInfo.value())).append( "\n\n");
  25. }
  26. }
  27. sb.append( "Method注解:").append( "\n");
  28. Method[] methods = cls.getDeclaredMethods();
  29. for (Method method : methods) {
  30. MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
  31. if (methodInfo != null) {
  32. sb.append(Modifier.toString(method.getModifiers())).append( " ")
  33. .append(method.getReturnType().getSimpleName()).append( " ")
  34. .append(method.getName()).append( "\n");
  35. sb.append( "注解值: ").append( "\n");
  36. sb.append( "name: ").append(methodInfo.name()).append( "\n");
  37. sb.append( "data: ").append(methodInfo.data()).append( "\n");
  38. sb.append( "age: ").append(methodInfo.age()).append( "\n");
  39. }
  40. }
  41. System.out.print(sb.toString());
  42. }

所做的操作都是通过反射获取对应元素,再获取元素上面的注解,最后得到注解的属性值。

看一下输出情况,这里我直接显示在手机上:



这个自定义运行时注解是很简单的例子,有很多优秀的开源项目都有使用运行时注解来处理问题,有兴趣可以找一些来研究。因为涉及到反射,所以运行时注解的效率多少会受到影响,现在很多的开源项目使用的是编译时注解,关于编译时注解后面再来详细介绍。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@Retention注解作用 的相关文章

随机推荐

  • impala查询转义问题

    select REGEXP REPLACE 佰分贰拾 深圳 品牌管理有限公司 然后 SELECT vendor full name REGEXP REPLACE vendor full name FROM odsmdmdata sms ve
  • 面试 - Redis 多路复用原理

    大家都知道redis是单进程而且快 那你知道为什么吗 面试中我只能答出多路复用 但具体的原理又不知道了 很尴尬 不过也很欣慰 从一次又一次的失败中总结经验弥补不足 事实上有一定经验的人知识如果不够深已经不是什么问题了 不过还是得补下这个课
  • Python 图像处理之 JPEG 格式

    Python 图像处理之 JPEG 格式 JPEG Joint Photographic Experts Group 是一种常见的图像压缩格式 在数字图像处理 图像传输等领域得到广泛应用 Python 内置的 PIL 库提供了对 JPEG
  • Qt在软件运行过程中改变一个控件的样式

    需求 在软件运行过程中改变一个控件的样式 思路 使用qss的属性选择器 在qss文件中分别对控件的某个属性的不同属性值设置样式 当需要修改控件样式时 修改控件属性的值 并重新加载该控件的样式表 如何修改控件属性的值 可以先了解一下Qt的属性
  • IntelliJ IDEA插件系列:四大炫酷神器你值得拥有

    拥有了这四款插件 你就比别人领先一步 你的界面独一无二 1 Mario Progress Bar 这是基于 IJ 的 IDE 的 Mario 进度条 基于 Dmitry Batkovitch 的 Nyan 进度条 它展示了马里奥 Mario
  • 软件测试人员该学习 Python 的七个理由

    对于一个软件测试工程师来说 选哪一门语言来入手编程一直是件非常纠结的事情 当然立志做一辈子功能测试的人除外 值得庆幸的是 专门介绍软件 工具及网站服务的技术Blog上CarlCheo绘制了一张图表 告诉你该怎么开始伟大的码农航道 大多数好的
  • (六)练习:饮料自动售货机

    1 找出所有的原因 输入 并编号 1 投币5角 2 投币1元 3 按下 橙汁 按钮 4 按下 啤酒 按钮 2 找出所有的结果 输出 并编号 注意 不能写购买成功 饮料送出 因为若买橙汁 则应该送出橙汁 送出啤酒是不对的 若只写找零 则在画因
  • mybatis:mybatis再总结

    1 什么是mybatis 优点 缺点 适用场合 与Hibernate的对比 https www cnblogs com zhai1997 p 12527689 html 2 和 的区别是什么 是预编译处理 是字符串替换 将传入的数据都当成一
  • Pytorch基础学习(第四章-Pytorch损失优化)

    课程一览表 目录 一 权值初始化 1 梯度消失与爆炸 2 Xavier方法与kaiming方法
  • unity 设置layer 使碰撞器不碰撞

    做游戏时 有时候需要让同一个地图的两个敌人不互相碰撞 但是两个人都有碰撞器 能站在地上 这个功能是如何实现的呢 答案就是设置layer 当点击Hierarchy窗口中的某个对象时 在Inspector窗口就可以看见Layer选项 如图 你可
  • Lua 15分钟快速上手(下)

    本系列相关文章 Flutter 热更新及动态UI生成 Lua 15分钟快速上手 上 Lua 15分钟快速上手 下 Lua与C语言的互相调用 LuaDardo中Dart与Lua的相互调用 进阶语法篇 迭代器 迭代器 iterator 是一种可
  • SpringMVC路径匹配中使用通配符

    SpringMVC路径匹配中使用通配符 RequestMapping中指定的路径也可以使用通配符 表示任意字符 如下的处理器方法可以映射请求 antstyle a 可以映射请求 antstyle b 但是它不能映射请求请求 antstyle
  • 创建或打开c++浏览数据库文件时发生错误,IntelliSense和浏览信息将不能用于C++项目。

    在用vs新建项目 出现这一类的错误 常出现在vs2010中 在使用VC2010的时候出现问题如下 创建或打开C 浏览数据库文件XXXXXXX stdf时发生错误 IntelliSense和浏览信息将不能用于C 项目 请确保已安装Micros
  • 多款知名App宣布停止更新,安卓用户大悲

    程序员的成长之路 互联网 程序员 技术 资料共享 关注 阅读本文大概需要 5 分钟 来自 电脑报 ID CQCPCW 开屏广告早已入侵我们的生活 如同狗皮膏药般存在 人人都在骂 却屡禁不止 甚至还被玩出各种新花样 比如关闭按钮小如蝼蚁 伪装
  • CocosCreator JS追踪堆栈信息

    在开发过程中 可能有这样的需求 即使在没有报错的情况 也需要查看该函数的堆栈调用信息 对于这样的需求 我们可以使用JS原生的console trace来实现 具体代码 export let TraceArr console trace fu
  • 服务器多网卡多路由策略

    场景背景与需求 某公司新买一台服务器 服务器资源 cpu 内存 硬盘 比较多 并且有多个网卡 运维工程师为了节省资源 在服务器上搭建多个服务 希望通过多个网卡实现流量分流 但由于运维工程师对网络理解不够深入 将服务器的多个网卡都配置了同一个
  • 被suse搞到崩溃了

    在Vmware上装了个suse 10 2 它还没崩溃 我快要崩溃了 这玩意号称最新最强的Linux 但是启动速度真的是慢的没法说 关机也是慢的没法说 点个按钮 半天才出来对话框 有时我都怀疑他是不是死掉了 多点几下 结果过一会出来一堆对话框
  • 2015年底总结

    时间过的好快 一年又过了 回顾这一年 经历了很多 成长了很多 今天对2015做一个简单的总结 同时展望一下未来 在14年总结中 今年的重点是考注册电气工程师 学习Android开发 在技术这块儿往精学 而不是多而不精 这一年 确实在注电考试
  • QQuickWidget里放置QML

    1 效果 2 QML 在资源里新建Mybattery qml import QtQuick 2 0 import QtQuick 2 12 Item id root property color color1 18FD18 绿色 健康 pr
  • @Retention注解作用

    Retention作用是定义被它所注解的注解保留多久 一共有三种策略 定义在RetentionPolicy枚举中 从注释上看 source 注解只保留在源文件 当Java文件编译成class文件的时候 注解被遗弃 被编译器忽略 class