详解Java注解( Annotation )

来源:互联网 发布:飞行器控制用什么编程 编辑:程序博客网 时间:2024/06/15 23:23

详解Java注解( Annotation )

注解的定义:

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释

注解的作用

  • 生成文档
  • 代码分析,通过代码里的元数据来对代码进行分析
  • 在编译的时候进行检查

JDK自带的注解

在开发过程中,我们见到的JDK自带的注解主要有三个,分别是@Override@SuppressWarnings@Deprecated,作用分别如下:

  • @Override

    • 主要用于标识所用的方法是继承自父类的方法,从而在编译的过程中可以被编译器检测到,如果某个方法使用了该注解,但是方法的签名(方法名以及参数类型)与父类不一致,则在编译的过程中,编译器会抛出错误,用于提示开发者。
    • 最常见的就是toString()方法了,该方法继承自Object类。如果我们在重写该方法的时候,没有使用该注解,然后不小心将该方法的名字写错如下所示:
    package cn.xuhuanfeng.annotation;public class TestAnnotation {public static void main(String[] args) {        TestAnnotation test = new TestAnnotation();        System.out.println(test.toString());    }    public String tostring() {        return "Not true";    }}

    输出结果为:cn.xuhuanfeng.annotation.TestAnnotation@15db9742,显然我们可以看到,toString()方法输出的结果显然不是我们所期待的,有时候就会很莫名其妙了(原因是重写toString() 方法的时候,不小心将S写错成了s,编译器会理解成有一个新的方法,叫tostring(),这是正确的,所以就导致了调用的时候出现了预期之外的结果了),但是如果我们在重写toString()方法的时候,加上@Override,这个时候,如果还是按照上面的写法,编译器就会告诉我们The method tostring() of type TestAnnotation must override or implement a supertype method,于是,我们很容易就能发现问题所在了,这是注解的好处之一,也是@Override 的作用,具体可以查看其源码即可。

  • @Deprecated

    • 主要用于标识该包、方法、域、变量等已经不推荐使用了,一旦标识了该注解,则对应的方法、域等会划上删除线如下所示
    @Deprecatedpublic void test(){    System.out.println("Deprecated");}
  • @SuppressWarnings

    • 主要用于压制编译器发出的警告,该注解需要提供参数,包括了unchecked all 等,分别对应不同的压制范围,如:
    @SuppressWarnings("all")public void test01(){}

自定义注解

上面我们看到了JDK中自带的注解,虽然很有用,但是毕竟范围有限,种类也有限,实用性不是很大,于是Java开发者为我们提供了自定义的注解,极大了扩展了该功能,下面我们就详细来看下自定义注解的内容。

元注解

为了使用自定义注解,首先我们需要了解一个概念:元注解,所谓的元注解,其实就是注解的注解,也就是用来表示注解的注解,JDK中包含的元注解中比较常用的有以下几种类型: @Target , @Retention , @Documented , @Inherited ,其中前面两种在实际开发过程中用得比较多,所以下面我们着重来介绍这两种:

  • @Target :
    • 用于表示所标识的注解的使用范围,其值可以是 ElementType.PACKAGE , ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD 等,分别对应的标识对象为 包,构造器,方法,域变量,也就是说,只有包含了该范围,我们定义出来的注解才能用于对应的域,多种类型可以组合使用,只需要使用{}包括起即可。
    • 具体使用如下:
      @Target({ElementType.PACKAGE,ElementType.CONSTRUCTOR ,ElementType.METHOD, ElementType.FIELD})
  • @Retention

    • 用于标识注解的存活周期,包括了RetentionPolicy.RUNTIME,RetentionPolicy.CLASS,RetentionPolicy.SOURCE,分别对应存活周期为运行时,字节码,源文件。
      • 运行时:标识该注解存在于字节码中,并且在运行过程中会被JVM加载,可用于反射操作。
      • 字节码:标识该注解存在于字节码中,但是运行时不被JVM加载,默认的形式。
      • 源文件:标识该注解只存在源文件中,在编译过程会被编译器丢弃。
    • 具体使用如下:
    @Retention(RetentionPolicy.RUNTIME)

自定义注解

学习完了元注解之后,我们就可以开始手动编写自定义的注解了。

  • 格式:
    自定义注解的书写方式跟普通的Java类的书写方式接近,只是将class 关键字替换为@interface ,如下:

    @Retention(RetentionPolicy.RUNTIME)@Target({ElementType.PACKAGE})public @interface MyAnnotation {}

    从上面的元注解部分我们可以知道,我们定义的注解MyAnnotation 只能用于注解包,而不能用于注解方法、域等。

  • 参数:
    从前面的@SuppressWarnings 中我们可以知道,注解还可以带参数,不过在注解中的参数类型有点奇怪,如下:

    String value();// String为参数类型 value() 整体为变量String[] value(); // String[] 为参数类型 value() 整体为变量

    默认情况下,如果只有一个参数类型,我们将变量命名为value(),我们也可以声明多个参数

      String name();  int age(); // 其他类型依此类推

    在注解中的所有参数均可以指定默认的值,如下:

    String name() default "";int age() default -1;

    由于在使用注解中我们无法标识错误的情况,所以一般情况下,会将默认类型指定为一个不合理值,用来处理注解时判断所使用的值是合理还是不合理。

  • 使用:
    定义完了一个我们的自定义注解之后,接下来我们来看下如何使用它。使用的方式跟JDK自带的注解的方式基本一致,指定对应的键值对,key为定义的参数名字,值为需要传入的值,如果是数组类型,则传入数组即可。

    @MyAnnotation(name="xuhaunfeng",age=23)public void test(){}//在MyAnnotation中多增加一个变量为 String[] parents();@MyAnnotation(name="xuhaunfeng",age=23,parents={"AA","BB"})public void test(){}

注解的应用

看完了上面的内容,可能你会觉得如果注解只是上面的用法,感觉上是没有任何作用的,确实,上面所介绍的内容都是注解的格式、定义等,但是没有涉及到其应用,注解配合反射,可以实现很多功能,例如:ORM的实现,框架中Annotation的应用等,不过目前我还没有学习到这些内容,所以在后期学习之后将会补上,敬请期待。

参考说明

这篇文章只是我个人学习过程中的一些笔记,不带有任何的商业目的,在学习过程中参考了很多的资料,主要参考深入理解Java:注解(Annotation)自定义注解入门 By竹子,在此对竹子表示感谢。如果本文涉及的一些内容有一些版权争议,还请与我联系。

0 0
原创粉丝点击