详解Java注解(Annotation)
从JDK5开始,Java增加了对元数据的支持,也就是注解Annotation。注解就是代码里的特殊标记,这些标记可以在编译、类加载和运行时被读取,并进行相应的处理。通过使用注解,开发人员可以在不改变原有逻辑的基础上,在源文件中嵌入一些补充信息。 Annotation是一个接口,程序可以通过反射机制来获取指定程序元素的Annotation对象,然后通过Annotation对象来取得注解中的元数据。值得注意的是,Annotaion并不影响程序的执行,无论添加、删除注解,代码都照常运行。
1.基本注解
Java提供了几个基本的注解,功能如下:
- @Override:用来指定方法重载,它可以强制一个子类必须重写父类的方法。@Override只能修饰方法,不能修饰其他程序元素。
- @Deprecated:@Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的程序元素时,编译器会发出警告。
- @SuppressWarnings:@SuppressWarnings只是被该注解修饰的程序元素(以及该程序元素的所有子元素)。取消指定的编译器警告。
2.元注解
在java.lang,annotation包下提供了几个元注解Meta Annotation,主要用于修饰其他的Annotation定义,具体如下:
- @Retention:只能用于修饰Annotation定义,指定被修饰的Annotation可以保留多长时间。 @Retention内部包含了一个RetentionPolicy变量,该变量可以取三个值: RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译时直接丢弃。 RetentionPolicy.CLASS:编译器将把Annotation记录在class文件中,当运行Java程序时无法获取 Annotation信息。改值为默认值。 RetentionPolicy.RUNTIME:目标类加载到JVM后依然保留,运行期可以通过反射获取注解信息。
- @Target:指定可以使用该注解的程序元素。内部使用ElementType指定该注解可以修饰哪些程序单元,如ElementType.METHOD表明注解可以修饰方法;ElementType.TYPE表示注解可以修饰类、接口等。
3.自定义注解
Java使用@interface修饰符定义一个注解类;注解的成员以无参数无抛出异常的方式声明;可以通过default关键字为成员指定一个默认值;成员的类型是受限的,合法的类型包括8种基本类型及其包装类、String、Class、enum和注解类型。
下面程序演示了一个自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//声明注解的保留期限——运行时有效
@Retention(RetentionPolicy.RUNTIME)
//声明该注解可以修饰的目标类型——注解作用于方法
@Target(ElementType.METHOD)
public @interface NeedTest{ //使用@interface定义注解
//声明注解成员,default指定其默认值
boolean value() default true;
}
上面程序使用@interface定义了一个注解类,这非常类似于定义了一个注解接口,这个注解接口继承了Annotation接口。值得注意的是,自定义的注解不可以显式实现接口或继承父类。
定义了@NeedTest注解后,就可以在任意方法上使用该注解,实例如下:
public class BookService {
@NeedTest(value=true)
public void deleteBook(long bookId){
System.out.println("删除图书:" + bookId);
}
@NeedTest(false)
public void addTopic(long bookId){
System.out.println("添加图书:" + bookId);
}
}
从上例可以看出,如果注解只有一个成员,则该成员名必须为value(),在使用时可以忽略成员名value和赋值号=。当注解有多个成员时,如果仅对value()成员赋值,也可以不指定成员名,但如果同时对多个成员赋值,则必须使用”成员名=值”的形式。
4.通过反射提取注解信息
自定义Annotation后,这些Annotation不会自动生效,必须又开发中提供相应的工具提取并处理Annotation的信息。Java5在java.lang.reflect包下新增了AnnotatedElement接口,该接口表示程序中可以接受注解的程序元素,它的实现类包括Class、Constructor、Field、Method、Package。因此可以通过Java反射机制对注解进行解析处理。下面程序定义一个注解解析器:
import java.lang.reflect.Method;
//注解的工具类
public class NeedTestUtil {
public static void main(String[] args) throws Exception {
BookService bookService = new BookService();
//获取被注解修饰的目标类
Class<?> clazz = BookService.class;
//获取所有方法
for (Method method : clazz.getDeclaredMethods()){
//判断当前方法是否被NeedTest注解修饰
if (method.isAnnotationPresent(NeedTest.class)){
NeedTest needTest = method.getAnnotation(NeedTest.class);
//如果NeedTest的value成员为true,则进行测试
if (needTest.value()){
System.out.println(method.getName() + "方法需要进行测试");
System.out.println("测试结果:");
method.invoke(bookService, Math.round(Math.random() * 100));
}
else {
System.out.println(method.getName() + "方法不需要进行测试");
}
}
}
}
}
通过上述程序,实现了一个类似Junit测试框架的@Test注解。
- 【腾讯云的1001种玩法】十分钟搞定云架构 · 什么是Bucket、什么是Object
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构 · 负载均衡的最佳实践
- 【黑客浅析】像黑客一样思考
- 【腾讯云的1001种玩法】 十分钟轻松搞定云架构 · 负载均衡的几种均衡模式
- ASP.NET Web API的Controller是如何被创建的?
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构:COS的两种上传模式
- 物流行业迎变革,云计算是基础,大数据是关键
- Socket学习总结系列(二) -- CocoaAsyncSocket
- 比特币勒索病毒肆虐,腾讯云安全专家给你支招
- HTML5 直播协议之 WebSocket 和 MSE
- IoC在ASP.NET Web API中的应用
- 跟鹅厂老司机学技术之一:“遇见” Kotlin
- 简单的 H5 视频推流解决方案
- 来腾讯云开发者实验室学习.NET
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- java中的阻塞队列
- java虚拟机
- 重构:保持Dockerfile整洁的5个技巧
- spring boot启动过程
- 如何构造jvm的堆溢出和栈溢出
- 一日一技:导入父文件夹中的模块并读取当前文件夹内的资源
- Matpotlib绘图遇到时间刻度就犯难?现在,一次性告诉你四种方法
- Windows NetLogon权限提升漏洞(CVE-2019-1424) 复现
- 源码解析:Git的第一个提交是什么样的?
- 终于搞懂,为什么 Java 的 main 方法必须是 public static void?
- Spring Boot 多版本更新,紧急修复 RFD 安全漏洞
- 【查找】折半查找/二分查找
- Kubernetes 1.19.0——密码管理
- centos 安装软件的方法
- 【深入理解java集合系列】ArrayList实现原理