Java 注解
一、概念和基本注解? ? 从JDK1.5开始,引入了源代码中的注解这一机制。注解使得 Java 源代码中不但可以包含功能性的实现代码,还可以包含元数据。 ? ? 那么什么是元数据呢?所谓元数据,就是描述数据的数据。比如说一张图片,图片内容是它的主体数据,那么像图片的创建时间、修改时间、创建者等等这些数据,就是这张图片的元数据。 ? ? 那么元数据有什么用呢?我们可以用元数据来创建文档、跟踪代码的依赖性和执行编译时的格式检查,并可以代替系统中原有的配置文件。 ? ? Java 注解是 Java 代码里的特殊标记,为我们在代码中添加用 Java 程序无法表达的额外信息提供了一种格式化方法,使我们可以在编译、类加载、运行时使用这些被注解修饰的程序元素(这些程序元素包括:类、属性、方法等)。 ? ? 使用注解时要在其前面加上一个 “@” 符号,表明后面的内容为注解。 ? ? 在 Java 的 java.lang 包中,预定义了三个注解,它们分别是限定重写父类方法的@Override、标记已过时的@Deprecated和抑制编译器警告的@SuppressWarnings,通常称这三个注解为内建注解或基本注解。 ? ??@Override 在我们编程过程中经常遇到,就不细讲了;@Deprecated 表示该类成员已经过时,在未来的版本中可能会被删除,不建议使用。@SuppressWarnings 和前两个注解有些不同,这个注解带有一个属性,表示要抑制什么样的警告信息,相关属性值的含义如下: @SuppressWarnings(value = "deprecation") //使用了过时的程序元素 @SuppressWarnings(value = "unchecked") 执行了未检查的转换 @SuppressWarnings(value = "unused") 有程序元素未被使用 @SuppressWarnings(value = "fallthrough") switch 程序块直接通往下一种情况,而没有break @SuppressWarnings(value = "path") 在类路径中有不存在的路径 @SuppressWarnings(value = "serial") 在可序列化的类上缺少 serialVersionUID 定义 @SuppressWarnings(value = "finally") 任何 finally 子句不能正常完成 @SuppressWarnings(value = "all") 所有情况 二、自定义注解? ? 注解之所以强大,能被众多框架所使用的主要原因在于,它可以允许程序员自定义注解,使 Java 程序变成自描述的。注解的语法形式和接口差不多,只不过在 interface 前面多了一个 @ 符号。 ? ? 我们可以在自定义注解时定义属性,在注解类型的定义中以无参方法的形式来声明,其方法名和返回值分别定义了该属性的名字和类型。另外需要注意的是,使用带属性的注解时,需要给属性赋值,不过可以在定义注解时,给属性赋默认值。 ? ??Java中注解成员的类型必须是如下几类:? 1. 基本数据类型(boolean,byte,char,short,int,long,float,double); public @interface MyAnnotation { String name() default "张三"; int age() default 22; } 三、元注解? ? 上面提到了元数据——描述数据的数据。还有一个元注解的概念,即描述注解的注解——使用不同注解对注解进行注解。Java 为注解单独提供了四种元注解,即@Target、@Retention、@Documented和@Inherited。下面将分别介绍这四种元注解。 ? ? 1、@Target? ? 使用 @Target 注解的目的是用于指定被修饰的注解能用于修饰哪些程序元素。如果注解定义中不存在 @Target 元注解,则此注解可以用于任意程序元素上,如果存在这样的元注解,则编译器强制实施指定的使用规则。 /** * ElementType.ANNOTATION_TYPE : 限制此注解用于注解类 * ElementType.CONSTRUCTOR : 限制此注解用于构造方法 * ElementType.FIELD : 限制此注解用于字段属性(包括枚举变量) * ElementType.LOCAL_VARIABLE : 限制此注解用于局部变量声明 * ElementType.METHOD : 限制此注解用于方法声明 * ElementType.PACKAGE : 限制此注解用于包声明 * ElementType.PARAMETER : 限制此注解用于参数声明 * ElementType.TYPE : 限制此注解用于类、接口(包括注解类型)或枚举声明 */ @Target({ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.LOCAL_VARIABLE,ElementType.METHOD,ElementType.PACKAGE,ElementType.PARAMETER,ElementType.TYPE}) MyAnnotation { } ? ?Java 8 新增加了两个注解的程序元素类型 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER。现在我们几乎可以在所有的地方:局部变量、泛型、超类和接口实现、甚至是方法的Exception声明: public class Annotations { @Retention( RetentionPolicy.RUNTIME ) @Target( { ElementType.TYPE_USE,ElementType.TYPE_PARAMETER } ) NonEmpty { } static class Holder< @NonEmpty T > extends @NonEmpty Object { void method() throws @NonEmpty Exception { } } void main(String[] args) { final Holder< String > holder = new @NonEmpty Holder< String >(); @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>(); } } 2、@Retention? ? @Retention 用于指定被修饰的注解的生命周期,生命周期分为三种,分别是?RetentionPolicy.CLASS、RetentionPolicy.RUNTIME 和?RetentionPolicy.SOURCE。如果注解定义中不存在 @Retention 元注解,则生命周期默认为 RetentionPolicy.CLASS。 * RetentionPolicy.CLASS : 编译器将把注解记录在 class 文件中,当运行 Java 程序时,虚拟机不再保留注解。 * RetentionPolicy.RUNTIME : 编译器将把注解记录在 class 文件中,当运行 Java 程序时,虚拟机保留注解,程序可以通过反射获得该注解。 * RetentionPolicy.SOURCE : 编译器将直接丢弃被修饰的注解 @Retention(RetentionPolicy.RUNTIME) ; } TestMyAnnotation { void main(String[] args) NoSuchMethodException,ClassNotFoundException { TestMyAnnotation testMyAnnotation = new TestMyAnnotation(); testMyAnnotation.getObjectInfo(); } @MyAnnotation @Deprecated void getObjectInfo() ClassNotFoundException,NoSuchMethodException { Annotation[] annotations = Class.forName("annotation.TestMyAnnotation").getMethod("getObjectInfo").getAnnotations(); for (Annotation annotation : annotations) { System.out.println("该注解是" + annotation); if (annotation instanceof MyAnnotation) { MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println(myAnnotation.name()); System.out.println(myAnnotation.age()); } } } }TestMyAnnotation.java ? ? 3、@Documented? ? 在默认的情况下,使用 javadoc 工具自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用?@Documented 注解。 @Documented MyAnnotation { } ? ? 4、@Inherited? ? 默认情况下,父类的注解不被子类继承,如果要想继承父类注解,就必须使用 ?@Inherited 注解。 @Inherited MyAnnotation { } 四、总结? ? 其实,Java 注解可以简单理解成一种标记符号、描述信息。强大的并不是注解本身,而是对注解的灵活使用。以 Spring 常见的 ?@Component?注解为例。Spring 在启动时,上下文利用反射找到包路径下带有?@Component 的类,然后把它装载成 Spring 的 Bean。 (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |