java之美妙的注解

  java之美妙的注解
  
  注解
  
  一、认识注解
  
  先看百度百科对java注解的解释:
  
  定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
  
  作用分类:
  
  ①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
  
  ② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
  
  ③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
  
  提到的元数据,可以理解为描述数据的数据,看起来很绕,元注解也是描述注解的注解,后面说。
  
  Annotation都是java.lang.annotation.Annotation接口的子接口,注解是一种特殊的接口,从代码格式上来看确实是,是在interface前加了一个@符号,格式为@interface xxx{}
  
  二、JDK内置注解
  
  jdk就存在注解,比如我们用eclipse子类覆盖父类方法时候用快捷间alt+/会自带在方法名称上面贴上一个@Override的标签。
  
  @Override
  
  这个就是在子类覆盖父类的方法时候,经常遇到
  
  @Deprecated
  
  这个元素是用来标记过时的元素,想必大家在日常开发中经常碰到。编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量。 如java.util.Data类中有很多过时的方法
  
  @SupressWarings
  
  抑制警告,有很多人有代码洁癖,看到黄色的警告不爽,用它就可以抑制住。
  
  @SafeVarargs
  
  java7出现的,抑制堆污染警告,有点自欺欺人的感觉。
  
  三、元注解
  
  元注解就是注解的注解,来看一下有哪些元注解
  
  @Retention
  
  Retention英文是保留的意思,在这里可以约束注解的存活周期,代码运行有三个周期,分别为Source(源代码)、Class(字节码)、Runtime(运行时期) 三个时期的值保留在RetentionPolicy这个枚举类中。所以我们可以这样来玩,
  
  @Retention(RetetionPolicy.常量值)//RESOURCE,CLASS,RUNTIME
  
  @Target
  
  Target是目标的意思,这里约束这个注解在那可以贴(类,方法,构造器,参数等),位置的常量在ElementType这个枚举类中
  
  @Target({ElementsType.常亮值})//TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE表示类,接口,枚举
  
  @Documented
  
  Document文档的意思,也就是使用这个标签到时候会带到API文档中去
  
  @Inherited
  
  Inherited是遗传的意思,顾名思义,这个注解会遗传到子类去
  
  @Repeatable 可重复的,Java8的一个新特性
  
  四、自定义注解
  
  1.注解的属性
  
  在注解中定义属性,必须是8 种基本数据类型外加 类、接口、注解及它们的数组。不能是Integer..注解中属性可以有默认值,默认值需要用 default 关键值指定。
  
  如:
  
  @interface TestAnnotation{
  
  int id() default 0;
  
  String msg() default "hello";
  
  }
  
  @TestAnnotation(id = 3,msg = "aa")
  
  class Test1{
  
  }
  
  //当注解中只有一个value属性时候,贴标签的时候可以省略value。
  
  //当注解中没有属性时,括号都可以省略(www.meiwanyule.cn override注解)
  
  @interface Test1Annotation{
  
  int[] value();
  
  }
  
  @Test1Annotation({1,2})
  
  class Test2{
  
  }
  
  2.用反射操作注解
  
  注解可以在类Class,方法Method,字段Field,构造器Constructor上等,所以在各自的类中都存在获取注解的API
  
  boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
  
  如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
  
  Annotation[] getAnnotations() 返回此元素上存在的所有注释。
  
  <Annotation>  getAnnotation(Class annotationClass)如果存在该元素的指定类型的注释,则返回这些注释对象,否则返回 null。 获取注解对象
  
  自定义一个注解:
  
  @Target({TYPE, FIELD,www.dfgjpt.com/ METHOD})//注解可以放的目标
  
  @Retention(RetentionPolicy.RUNTIME)//注解保留周期
  
  public @interface AnnotationTest {
  
  int id();
  
  String name();
  
  }
  
  测试一下这个自定义的注解:
  
  @AnnotationTest(id =www.furggw.com  1,name = "na")
  
  class Test{
  
  public static void main(String[] args) throws Exception {
  
  //判断Test(类元素)是否应用了这个注解
  
  boolean hasAnnotation = Test.class.isAnnotationPresent(AnnotationTest.class);
  
  if(hasAnnotation){
  
  //获取注解对象
  
  AnnotationTest t = Test.class.getAnnotation(AnnotationTest.class);
  
  System.out.println(t.name());
  
  System.out.println(t.id());
  
  //获取所有的注解s
  
  Annotation[] ans =www.mcyllpt.com Test.class.getAnnotations();
  
  for (Annotation an : ans) {
  
  System.out.println(an);
  
  }
  
  }
  
  System.out.println("============");
  
  //获取方法中上的注解
  
  boolean has = Test.class.getMethod("work").isAnnotationPresent(AnnotationTest.class);
  
  if(has){
  
  AnnotationTest an = Test.class.getMethod("work").getAnnotation(AnnotationTest.class);
  
  System.out.println(an.name());
  
  }
  
  }
  
  @AnnotationTest(id = 0,name="hello")
  
  public void work(www.dasheng178.com){
  
  }
  
  }
  
  结果为:
  
  na
  
  1
  
  @annotation.AnnotationTest(id=1, name=na)
  
  ============
  
  hello
  
  五、注解的用途
  
  实践:模拟Junit4.x
  
  Junit是做单元测试的,junit4用了注解,用法是在一个公共无参的方法贴上一个@Test标签表示要测试这个方法,但是在测试之前有可能会出现一些初始化操作,在结束后可能需要释放一些资源,需要初始化的方法上面贴上一个@Before,Test之后需要执行的需要贴上@After。
  
  现在我们来自定义注解来模拟一下这些操作,需要在这里提的是,其实注解本身没什么意义,需要人为的设置它完成一些功能。
  
  我们先定义三个注解:
  
  @Target(ElementType.METHOD)
  
  @Retention(RetentionPolicy.RUNTIME)
  
  public @interface MyAfter {
  
  }
  
  @Retention(RetentionPolicy.RUNTIME)
  
  @Target(ElementType.www.ysyl157.com METHOD)
  
  public @interface MyBefore {
  
  }
  
  @Target(ElementType.METHOD)
  
  @Retention(RetentionPolicy.RUNTIME)
  
  public @interface MyTest {
  
  }
  
  来一个测试这些注解功能的类
  
  public class Employee {
  
  @MyBefore
  
  public void init(){
  
  System.out.println("-------初始化-------");
  
  }
  
  @MyAfter
  
  public void end(){
  
  System.out.println("-------销毁---------");
  
  }
  
  @MyTest
  
  public void save() {
  
  System.out.println("保存操作");
  
  }
  
  @MyTest
  
  public void delete() {
  
  System.out.println("删除操作");
  
  }
  
  @MyBefore
  
  public void ddd(){
  
  System.out.println("怎么说呢?");
  
  }
  
  }
  
  好了,接下来我们就得具体去设置这个注解的意义
  
  思路和步骤:
  
  获取Employee类的字节码对象,得到所有的方法
  
  对所有方法进行迭代,将三类注解分别存储,把有@MyBefore注解的存在beforeList,带有@MyAfter存在afterList,带有@MyTest存在testList
  
  对testList集合迭代,在迭代 过程中先执行beforeList中的方法,在执行afterList中的方法
  
  public class JunitTest {
  
  public static void main(String[] args) throws Exception {
  
  //得到Employee中所有的方法
  
  Method[] mds = Employee.class.getDeclaredMethods();
  
  //创建Employee的对象,用来执行方法
  
  Employee e = Employee.class.newInstance();
  
  //用集合存储三类注解标注的方法
  
  List<Method> beforeList = new ArrayList<>();
  
  List<Method> afterList = new ArrayList<>();
  
  List<Method> testList = new ArrayList<>();
  
  //对所有的方法进行迭代,分类
  
  for (Method md : mds) {
  
  if(md.isAnnotationPresent(MyBefore.class)){
  
  beforeList.add(md);
  
  }else if(md.isAnnotationPresent(MyAfter.class)){
  
  afterList.add(md);
  
  }else if(md.isAnnotationPresent(MyTest.class)){
  
  testList.add(md);
  
  }
  
  }
  
  //在对test迭代的过程中,先执行所有被before注解了的方法,然后执行test注解的方法,最后再执行after注解了的方法
  
  for (Method method : testList) {
  
  for (Method before : beforeList) {
  
  before.invoke(e);  //方法都没有参数
  
  }
  
  method.invoke(e);
  
  for (Method after : afterList) {
  
  after.invoke(e);
  
  }
  
  }
  
  }
  
  }
  
  结果:
  
  -------初始化-------
  
  怎么说呢?
  
  删除操作
  
  -------销毁---------
  
  -------初始化-------
  
  怎么说呢?
  
  保存操作
  
  -------销毁---------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值