前话:

今天,我们又来聊一下注解的使用,做一下详细的解析,也介绍了自定义注解,请耐心往下看哟!

注解的介绍:

在2005年,sun公司推出了jdk1.5,同时推出的注解功能吸引了很多人的目光,使用注解编写代码,能够减轻java程序员繁琐配置的痛苦。

使用注解可以编写出更加易于维护,bug更少的代码。

注解是什么呢?按照官方的说法,注解就是元标签,可以添加到你的代码,并应用于包声明、类型声明、构造函数、方法、字段、参数和变量。

注解提供了一种非常有用的方法来显示你编写的方法是否依赖于其他方法,它们是否完整,编写出的类是否引用了其他类,等等。

按照 Oracle官方 的说法,基于注解编写出的java代码会根据源代码中的注解生成模板代码,从而避免我们在大多数情况下编写模板代码。这导致了一种声明式编程风格,在这种风格中,程序员说要做什么功能,工具就写出相应的代码来实现它。

简而言之,注解是一种机制,用于将元标签与程序元素相关联,并允许编译器或虚拟机从这些注解元素中提取程序行为,并在必要时生成相互依赖的代码。

那么,现在就开始我们的java注解学习之旅。

内置注解

ava会内置一些已经实现好的注解,可以直接使用,内置的注解主要用于给java编译器提供指令。

Java内置的注解有五个:

  • @Deprecated
  • @Override
  • @SuppressWarnings
  • @SafeVarargs
  • @FunctionalInterface

1. @Deprecated 注解主要用于给类、方法、变量打上不建议使用的标签,如果你的代码使用了不建议使用的类、方法、变量,编译器就会给你一个警告。

下面是使用@Deprecated的示例:

public class AnnotationTest {public static void main(String args[]){MyAnnotation myAnnotation = new MyAnnotation();int age = myAnnotation.age;myAnnotation.eat();}
}
@Deprecated
class MyAnnotation {@Deprecatedint age;@Deprecatedvoid eat(){}
}

定义了一个MyAnnotation,在类名,变量名和方法名上都使用的@Deprecated注解。

使用了@Deprecated标识的类、方法或变量时,

@Deprecated还有另外一个用处,就是在javadoc文档中写明类、方法或变量为什么不建议使用,并且给出替代方法:

@Deprecated
/**@deprecated 已废弃,请使用MyNewComponent.
*/
class MyComponent {}

2.@Override注解在方法上使用,标识这个方法重写父类的方法。如果这个方法和父类方法不一致,编译器就会显示错误。

强烈建议在重写父类的方法上使用@Override注解,不用也不会有什么影响,但是如果不使用@Override注解,当有人修改父类的方法时,你就无法识别出子类的方法是否重写了父类的方法。而使用了@Override注解,只要父类没有这个方法,编译器就会提示父类没有对应方法的错误。

下面是使用@Override注解的示例:

class Anaimal{public void run(){}
}
class Cat extends Anaimal{@Overridepublic void run(){}
}

Cat类的run()方法使用了@Override注解,如果将Cat类中的方法改为run1(),编译器就会显示The method run1() of type Cat must override or implement a supertype 的错误。

如果不使用@Override注解,将Cat类中的方法改为run1(),系统则不会报错。

3.@SuppressWarnings注解也是在方法上使用,用于抑制警告,在调用deprecated的方法或者进行不安全的类型转化时,编译器会发出一些警告,使用@SuppressWarnings就可以忽略那些警告。

使用示例:

@SuppressWarnings
public void methodWithWarning() {}

4.@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。

5.@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 {@TestAnnotationpublic 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 {@RuningTestpublic void test5km(){System.out.println("进行5公里跑步测试");}public void test10km(){System.out.println("进行10公里跑步测试");}@RuningTestpublic 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进阶架构资料的可以查看我专栏获取呢~

里面包括:(BATJ面试资料、高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)以及Java进阶学习路线图)哦。

也感谢你的阅读,我是小架

我们下篇文章见!

注解报错_Java中的注解使用:全面性的总结一下相关推荐

  1. 子类实现父类接口时注解为啥报错_Java中的注解使用:全面性的总结一下

    前话: 今天,我们又来聊一下注解的使用,做一下详细的解析,也介绍了自定义注解,请耐心往下看哟! 注解的介绍: 在2005年,sun公司推出了jdk1.5,同时推出的注解功能吸引了很多人的目光,使用注解 ...

  2. param注解报错_mybatis不加@Parm注解报错的解决方案

    我的idea版本2017.3.4,低版本貌似不会加上这个配置,idea高版本会 补充知识:Mybatis传多个参数的问题 及MyBatis报错 Parameter '0' not found. Ava ...

  3. java 注解报错_java注解验证接收参数 返回注解字段的错误

    1.在controller接口方法接收参数加上 @Valid注解 并且在实体类参数后紧跟 BindingResult bindingresul BindingResultMsgUtil工具类: pub ...

  4. controller 中@autowired 报错_Spring中常用注解

    创建对象的注解 @Component:创建对象 @Repository:创建DAO对象,用来访问数据库 @Service:创建Service对象,处理业务逻辑,可以有事务功能 @Controller: ...

  5. java sendredirect报错_java 中sendredirect()和forward()方法的区别

    HttpServletResponse.sendRedirect与RequestDispatcher.forward方法都可以实现获取相应URL资源. sendRedirect实现请求重定向,forw ...

  6. java注解和反射原理_Java中的注解和反射

    最近又回顾了一下 Java 中的注解和反射知识点,注解在日常开发中使用很多,但是反射比较少.值得注意的是 Java 的各种框架底层源码中大量使用了注解和反射,阅读源码,这些是基本功,面试中这部分内容也 ...

  7. java编码转换报错_Java中BeanUtils的日期转换 代码报错 怎么解决

    Person类:publicclassPerson{privateDatebirthday;publicDategetBirthday(){returnbirthday;}publicvoidsetB ...

  8. instanceof java 报错_java中instanceof怎么理解?java中instanc 爱问知识人

    1.用法表达式    result = object instanceof class     result:布尔类型.     object:必选项.任意对象表达式.     class:必选项.任 ...

  9. java常见的报错_Java中常见的错误有哪些?

    原标题:Java中常见的错误有哪些? 1.java.lang.Error 错误.是所有错误的基类,用于标识严重的程序运行问题.这些问题通常描述一些不应被应用程序捕获的反常情况. 原因: 1.对系统所访 ...

最新文章

  1. OpenCV使用 GrabCut 算法进行交互式前景提取
  2. win7完美兼容DynamipsGUI(小凡模拟器)攻略
  3. 前端学习(1308):URl
  4. 【数据结构与算法】【算法思想】动态规划
  5. 计算机应用领域变化,计算机应用领域与发展阶段.ppt
  6. (计算机组成原理)第三章存储系统-第二节:基本的半导体原件和存储器芯片的原理
  7. express不是内部或外部命令,也不是可运行的程序或批处理文件
  8. 《贝叶斯思维:统计建模的Python学习法》——2.5 封装框架
  9. Python生态工具、文本处理和系统管理(虚拟)
  10. 信号与线性系统翻转课堂笔记1
  11. nginx的安装和配置
  12. Unity AIUI
  13. c语言函数写巴德歌赫猜想,高三励志演讲稿范文
  14. 魅族M9同步谷歌联系人
  15. css5辅助线,苦练 CSS 基本功——图解辅助线的原理和画法
  16. bzoj 3356: [Usaco2004 Jan]禁闭围栏 离散化+树状数组
  17. PHP 开发环境配置
  18. C语言面试考点之一(常见关键字)
  19. 2019计算机考研百度云,2019计算机考研复习时间表(全年版)
  20. 【MybatisPlus 学习】MyBatisX 插件

热门文章

  1. vins中imu融合_基于非线性优化算法—当视觉SLAM遇到VINS会碰撞出怎样的火花?
  2. 怎么查电脑系统版本_电脑系统垃圾清理利器,专业、小巧且免费,有这一个就够了...
  3. LDD3源码分析之ioctl操作 .
  4. java需要前台封装对象吗_javaEE之-----------类反射直接封装前台传过来的参数
  5. linux wm虚拟机网络,复制多台虚拟机及简单的网络配置
  6. mysql登录服务器报错_mysql登录服务器报错
  7. 循环训练_力量循环训练
  8. kd树的根节点_kd树总结
  9. io读取一个文件再写入socket技术_JAVA中IO与NIO面试题
  10. android json mysql_Android通过json向MySQL中读写数据的方法详解【写入篇】