java注解使用总结
2005年,sun公司推出了jdk1.5,同时推出的注解功能吸引了很多人的目光,使用注解编写代码,能够减轻java程序员繁琐配置的痛苦。
使用注解可以编写出更加易于维护,bug更少的代码。
注解是什么呢?按照官方的说法,注解就是元标签,可以添加到你的代码,并应用于包声明、类型声明、构造函数、方法、字段、参数和变量。
注解提供了一种非常有用的方法来显示你编写的方法是否依赖于其他方法,它们是否完整,编写出的类是否引用了其他类,等等。
按照Oracle官方的说法,基于注解编写出的java代码会根据源代码中的注解生成模板代码,从而避免我们在大多数情况下编写模板代码。这导致了一种声明式编程风格,在这种风格中,程序员说要做什么功能,工具就写出相应的代码来实现它。
简而言之,注解是一种机制,用于将元标签与程序元素相关联,并允许编译器或虚拟机从这些注解元素中提取程序行为,并在必要时生成相互依赖的代码。
现在开始我们的java注解学习之旅。
内置注解
java会内置一些已经实现好的注解,可以直接使用,内置的注解主要用于给java编译器提供指令。
java内置的注解有五个:
- @Deprecated
- @Override
- @SuppressWarnings
- @SafeVarargs
- @FunctionalInterface
@Deprecated注解主要用于给类、方法、变量打上不建议使用的标签,如果你的代码使用了不建议使用的类、方法、变量,编译器就会给你一个警告。
下面是使用@Deprecated的示例:
public class AnnotationTest {
public static void main(String args[]){
MyAnnotation myAnnotation = new MyAnnotation();
int age = myAnnotation.age;
myAnnotation.eat();
}
}
@Deprecated
class MyAnnotation {
@Deprecated
int age;
@Deprecated
void eat(){
}
}
定义了一个MyAnnotation,在类名,变量名和方法名上都使用的@Deprecated注解。
使用了@Deprecated标识的类、方法或变量时,
@Deprecated还有另外一个用处,就是在javadoc文档中写明类、方法或变量为什么不建议使用,并且给出替代方法:
@Deprecated
/**
@deprecated 已废弃,请使用MyNewComponent.
*/
class MyComponent {
}
@Override注解在方法上使用,标识这个方法重写父类的方法。如果这个方法和父类方法不一致,编译器就会显示错误。
强烈建议在重写父类的方法上使用@Override注解,不用也不会有什么影响,但是如果不使用@Override注解,当有人修改父类的方法时,你就无法识别出子类的方法是否重写了父类的方法。而使用了@Override注解,只要父类没有这个方法,编译器就会提示父类没有对应方法的错误。
下面是使用@Override注解的示例:
class Anaimal{
public void run(){
}
}
class Cat extends Anaimal{
@Override
public void run(){
}
}
Cat类的run()方法使用了@Override注解,如果将Cat类中的方法改为run1(),编译器就会显示The method run1() of type Cat must override or implement a supertype
的错误。
如果不使用@Override注解,将Cat类中的方法改为run1(),系统则不会报错。
@SuppressWarnings注解也是在方法上使用,用于抑制警告,在调用deprecated的方法或者进行不安全的类型转化时,编译器会发出一些警告,使用@SuppressWarnings就可以忽略那些警告。
使用示例:
@SuppressWarnings
public void methodWithWarning() {
}
@SafeVarargs注解主要用于抑制参数类型安全检查警告,这个是jdk1.7新增的功能。
使用示例:
@SafeVarargs
static void testSafeVarargs(List<String> ... stringLists) {
Object[] array = stringLists;
List<Integer> tmpList = Arrays.asList(42);
array[0] = tmpList;
String s = stringLists[0].get(0);
}
如果不使用@SafeVarargs注解,编译器会给出警告信息:Type safety: Potential heap pollution via varargs parameter stringLists
。
使用@SafeVarargs有个前提,你必须保证某个使用了可变长度参数的方法,在与泛型类一起使用时不会出现类型安全问题。否则在运行行时会抛出 ClassCastException异常。
@SafeVarargs注解只能在满足如下条件的方法上使用:
- 参数长度可变的方法或构造方法。
- 方法必须声明为static或final。
@FunctionalInterface注解主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
使用示例:
@FunctionalInterface
interface GreetingService
{
void readMessage(String message);
}
创建注解
注解的创建和接口有点类似,都是使用interface关检字,区别是创建注解时,需要在interface前面加上一个@字符。
下面是创建一个注解的例子:
public @interface MyAnnotation {
}
上面创建注解没有任何成员变量。
创建带成员变量的注解:
@interface TestAnnotation{
int age();
String name();
}
TestAnnotation注解有两个成员变量,age和name。
注解的成员变量以无参数无方法体的方法形式声明。
使用default关键字指定注解成员变量的默认值:
@interface TestAnnotation{
int age() default 2;
String name() default “小明”;
}
使用自定义注解时,如果该注解的变量有默认值,可以不为成员变量指定值,直接使用默认值。
使用示例:
@interface TestAnnotation{
int age() default 2;
String name() default "小明";
}
class MyAnnotation {
@TestAnnotation
public void getInfo(){
}
}
如果注解的变量没有默认值,在使用时必须为每个变量都指定值,代码如下:
@interface TestAnnotation{
int age();
String name();
}
class MyAnnotation {
@TestAnnotation(age=2,name="小明")
public void getInfo(){
}
}
元注解
什么是元注解呢?元注解就是注解的注解,也就是用于定义注解的注解,可以理解为注解的基础数据类型。这玩意真的很拗口,还是看代码比较舒服。
@Target(ElementType.METHOD)
@interface Test_Target {
public String doTestTarget();
}
@Target就是元注解,用于定义Test_Target注解。
java提供五种元注解,分别是:
- @Retention 指定注解的生命周期,即存活时间。
- @Documented javadoc命令生成的文档中体现注解的内容
- @Target 指定注解可用于哪些元素,例如类、方法、变量等
- @Inherited 注解的继承性,
- @Repeatable 可重复使用的注解
@Retention用于指定注解的生命周期,即存活时间。@Retention提供了如下的三个值,在使用@Retention时,必须使用其中的一个值。
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译生成class文件时丢弃,无法通过反射获取注解信息。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到JVM中,无法通过反射获取注解信息,这是默认值。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,程序运行时可以通过反射获取到它们。
下面是使用@Retention定义一个自定义注解的示例:
@Retention(RetentionPolicy.RUNTIME)
@interface Test_Retention{
}
@Test_Retention
class MyAnnotation {
public void getInfo(){
}
}
上面的代码创建了一个Test_Retention的注解,并且使用@Retention指定Test_Retention注解可以保留到程序运行的时候(RetentionPolicy.RUNTIME),MyAnnotation使用@Test_Retention修饰,因此在运行时可以通过反射获取到MyAnnotation的注解信息。
@Documented如果类A使用了@Documented元注解注解的注解,那么在使用javadoc生成的类A的文档会包含有相应的注解信息。
使用示例:
@Documented
@interface TestDocument{
String doTestDocument();
}
@TestDocument (doTestDocument="保留注解信息测试")
class MyAnnotation {
public void getInfo(){
}
}
@Target指定了注解所修饰对象的范围,可用于变量、参数、方法、包信息等。
@Target元注解提供如下的八个值:
- ElementType.ANNOTATION_TYPE 用于描述注解类型
- ElementType.CONSTRUCTOR 用于注解构造方法
- ElementType.FIELD 用于变量注解
- ElementType.LOCAL_VARIABLE 用于局部变量注解
- ElementType.METHOD 用于方法注解
- ElementType.PACKAGE 用于包注解
- ElementType.PARAMETER 用于方法内的参数注解
- ElementType.TYPE 用于类、接口、枚举注解
代码示例:
@Target(ElementType.METHOD)
@interface TestMethodTarget{
}
@Target(ElementType.FIELD)
@interface TestFieldTarget{
}
@Target(ElementType.TYPE)
@interface TestTypeTarget{
}
TestMethodTarget注解只能用于注解类的方法,TestFieldTarget只能用于注解类的成员变量,TestTypeTarget可用于注解类、接口(包括注解类型) 或enum声明
@Inherited指定了注解可被继承。某个类使用了被@Inherited修饰的注解,那么那个注解也会用到该类的子类。
代码示例:
@Inherited
@interface TestInherited{
}
@Repeatable同一个注解可多次使用。例如一个人有多种爱好,跑步、画画、看电影等。
示例代码:
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String hobby default "";
}
@Person(hobby="runing")
@Person(hobby="drawing")
@Person(hobby="watching movies")
public class Tom{
}
上面的代码,@Repeatable 注解了 Person。而 @Repeatable后面括号中的类相当于一个容器注解。
什么是容器注解呢?就是用来存放其它注解的地方。它本身也是一个注解。
上面详细介绍了注解的知识以及自定义注解的语法。现在我们来看下如何使用注解进行单元测试。
使用注解这要到反射的知识,关于反射的知识请看我的另外一篇文章“Java反射使用总结”。在得到反射对象后,要调用isAnnotationPresent方法这个对象是否包含指定类型的注解。 Annotation
示例代码:
public class Marathonrunner {
@RuningTest
public void test5km(){
System.out.println("进行5公里跑步测试");
}
public void test10km(){
System.out.println("进行10公里跑步测试");
}
@RuningTest
public void test21km(){
System.out.println("进行21公里跑步测试");
}
public void test42km(){
System.out.println("进行42公里跑步测试");
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface RuningTest{
}
public class RuntestTool {
public static void main(String args[]){
Marathonrunner xiaoming = new Marathonrunner();
Class clazz = xiaoming.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(RuningTest.class)){
try {
method.setAccessible(true);
method.invoke(xiaoming, null);
} catch (Exception e) {
}
}
}
}
}
运行结果:
进行21公里跑步测试
进行5公里跑步测试
上面的代码,我们定义了一个RuningTest注解,里面没有任何变量。这个注解使用@Retention和@Target元注解修饰,其中@Target元注解的值规定了这个RuningTest注解只能在方法上使用,而@Retention元注解值指定了在运行时可以获取到注解的信息。
定义了一个Marathonrunner马拉松远动员类,里面有4个方法。
定义了一个专门用于测试Marathonrunner运动员方法的类。如果我们想测试某个类,只需在那个类上添加@RuningTest注解,不加@RuningTest注解的方法不会进行测试。test5km()和test21km()方法都加了@RuningTest注解,所以被测试到。
注解在spring,mybatis注解中广发应用。下次专门写篇文章讲下spring中注解的应用。
总结:
本文主要讲解了注解的概念,元注解的概念,如何自定义注解,以及如何使用自己定义注解进行单元测试。
java注解使用总结的更多相关文章
- Java注解
Java注解其实是代码里的特殊标记,使用其他工具可以对其进行处理.注解是一种元数据,起到了描述.配置的作用,生成文档,所有的注解都隐式地扩展自java.lang.annotation.Annotati ...
- 19.Java 注解
19.Java注解 1.Java内置注解----注解代码 @Deprecated //不推荐使用的过时方法 @Deprecated ...
- Java注解入门
注解的分类 按运行机制分: 源码注解:只在源码中存在,编译后不存在 编译时注解:源码和编译后的class文件都存在(如@Override,@Deprecated,@SuppressWarnin ...
- java注解(Annotation)解析
注解(Annotation)在java中应用非常广泛.它既能帮助我们在编码中减少错误,(比如最常见的Override注解),还可以帮助我们减少各种xml文件的配置,比如定义AOP切面用@AspectJ ...
- JAVA 注解的几大作用及使用方法详解
JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...
- attilax.java 注解的本质and 使用最佳实践(3)O7
attilax.java 注解的本质and 使用最佳实践(3)O7 1. 定义pojo 1 2. 建立注解By eclipse tps 1 3. 注解参数的可支持数据类型: 2 4. 注解处理器 2 ...
- paip.java 注解的详细使用代码
paip.java 注解的详细使用代码 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/att ...
- JAVA 注解的几大作用及使用方法详解【转】
java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解 ...
- 框架基础——全面解析Java注解
为什么学习注解? 学习注解有什么好处? 学完能做什么? 答:1. 能够读懂别人写的代码,特别是框架相关的代码: 2. 让编程更加简洁,代码更加清晰: 3. 让别人高看一眼. spring.mybati ...
- Java注解配置
Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annota ...
随机推荐
- 万万没想到,JVM内存结构的面试题可以问的这么难?
在我的博客中,之前有很多文章介绍过JVM内存结构,相信很多看多我文章的朋友对这部分知识都有一定的了解了. 那么,请大家尝试着回答一下以下问题: 1.JVM管理的内存结构是怎样的? 2.不同的虚拟机在实 ...
- Mysql索引进阶入门
1. 索引操作 MySQL 索引 菜鸟 2. 索引类型 PRIMARY 唯一且不能为空:一张表只能有一个主键索引 INDEX 普通索引 UNIQUE 唯一性索引 FULLTEXT 全文索引:用于搜索很 ...
- 前端模板引擎doT.js的用法
简介 一款简单好用的前端模板引擎 用法 <script type="text/javascript" src="js/doT.min.js">< ...
- XML学习(一)
本文主要记录xml学习过程中的一些笔记,包括xml作用,语法以及解析. 1.HTML和XML的区别 1.1.HTML 名称: HyperText Markup Languae(超文本标记语言) ...
- .net软件开发脚本规范-SVN标准
一. SVN标准 1) 提交代码前先获取最新代码 2) 提交时需要填写信息,填写任务Excel中的修改内容列,如以下任务填写“业绩考核-工作量管理”,如果发生修改再次提交,在其后加上修改原因,例“业绩 ...
- keras 学习-线性回归
园子里头看到了一些最基础的 keras 入门指导, 用一层网络,可以训练一个简单的线性回归模型. 自己学习了一下,按照教程走下来,结果不尽如人意,下面是具体的过程. 第一步: 生成随机数据,绘出散点图 ...
- ASP.NET Core on K8S深入学习(5)Rolling Update
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.什么是Rolling Update? 为了服务升级过程中提供可持续的不中断 ...
- MongoDB实现评论榜
Mongodb很适合做这件事,api的调用仅仅是使用到了入门级别的CRUD,理清楚了思路,编码也会顺风顺水,所以你会发现我在这篇博客中说的比编码还多 评论榜预期的功能 就像是StackOverFlow ...
- .net必问的面试题系列之面向对象
上个月离职了,这几天整理了一些常见的面试题,整理成一个系列给大家分享一下,机会是给有准备的人,面试造火箭,工作拧螺丝,不慌,共勉. 1.net必问的面试题系列之基本概念和语法 2.net必问的面试题系 ...
- springBoot框架分布式部署定时任务重复执行之解决方案
问题描述: 在集群模式部署服务端时,会出现所有的定时任务在各自的节点处均会执行一遍,这显然不符合实际的开发场景,针对这种问题,本文给出一种springboot集成shedlock的解决方案 第一步:引 ...