背景知识:
从JDK5开始提供名为Annotation(注释)的功能,它被定义为JSR-175规范。注释是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value="unchecked")。注释可以附加在package, class, method, field等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。如果没有外部解析工具等对其加以解析和处理的情况,本身不会对Java的源代码或class文件等产生任何影响,也不会对它们的执行产生任何影响。
元数据的作用,大致可分为三种:编写文档,通过代码里标识的元数据生成文档;代码分析,通过代码里标识的元数据对代码进行分析;编译检查,通过代码里标识的元数据让编译器能实现基本的编译检查。
JDK5内置的基本注释
JDK5内置了一些常用的注释,可以在编译时帮我们捕获部分编译错误,及提示信息,下面介绍下这些注释的用法:
1、@Override定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。例如我们为某类重写toString()方法却写成了tostring(),并且我们为该方法添加了@Override注释;代码如下:
public class OverrideDemo { @Override public String tostring() { return super.toString(); } } |
在编译时,会提示以下错误信息:
OverrideTest.java:4: 方法未覆盖其父类的方法 @Override ^1 错误 |
2、@Deprecated定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。使用@Deprecated的示例代码如下:
public class DeprecatedDemo { public static void main(String[] args) { DeprecatedClass.DeprecatedMethod(); } } class DeprecatedClass { @Deprecated public static void DeprecatedMethod() { // TODO } } |
在编译时,会得到以下提示信息:
注意:DeprecatedDemo.java 使用或覆盖了已过时的 API。 注意:要了解详细信息,请使用 -Xlint:deprecation 重新编译。 |
如果在编译时添加-Xlint:deprecation参数,我们能更清楚的看到该警告的详细信息,如下:
DeprecatedDemo.java:6: 警告:[deprecation] SomeClass 中的 DeprecatedMethod() 已过时 SomeClass.DeprecatedMethod(); ^1 警告 |
要注意@Deprecated与@deprecated的区别,@deprecated是为了生成文档的需要,例如:
class DeprecatedClass { /** * @deprecated 此方法已过时,不建议使用 */ @Deprecated public static void DeprecatedMethod() { // TODO } } |
3、@SuppressWarnings定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了,参数如下:
参数 | 说明 |
deprecation | 使用了过时的类或方法时的警告 |
unchecked | 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型 |
fallthrough | 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告 |
path | 在类路径、源文件路径等中有不存在的路径时的警告 |
serial | 当在可序列化的类上缺少 serialVersionUID 定义时的警告 |
finally | 任何 finally 子句不能正常完成时的警告 |
all | 关于以上所有情况的警告 |
通过上面的表格,你应该了解到每个参数的用意了,下面我就以一个常用的参数unchecked为例,为你展示如何使用@SuppressWarnings注释,示例代码如下:
import java.util.List; import java.util.ArrayList; public class SuppressWarningsDemo { public static List cache = new ArrayList(); //@SuppressWarnings(value = "unchecked") public void add(String data) { cache.add(data); } } |
当我们不使用@SuppressWarnings注释时,编译器就会有如下提示:
注意:SuppressWarningsDemo.java 使用了未经检查或不安全的操作。 注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。 |
下面我们去掉@SuppressWarnings(value="unchecked")这一行的注释符“//”,它会屏蔽编译时的警告信息,这也就是它所要达到的目的。
另外,由于@SuppressWarnings注释只有一个参数,并且参数名为value,所以我们可以将上面一句注释简写为@SuppressWarnings("unchecked");
同时参数value可以取多个值如:@SuppressWarnings(value={"unchecked", "deprecation"})
或@SuppressWarnings({"unchecked", "deprecation"})。
自定义Annotation注释
1、注释annotation与接口的异同:
因为annotation类型是一个非凡的接口,所以它与接口之间存在着某些差异:
A. Annotation类型使用关键字@interface而不是interface,这个关键字声明隐含了一个信息,它是继承了java.lang.annotation.Annotation接口,并非声明了一个interface。
B. Annotation类型的方法定义是独特的、受限制的,方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
C. Annotation类型又与接口有着近似之处,它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
2、自定义注释的实例:
下面,我们将看到如何定义annotation类型的例子。它展示了annotation类型声明以及@interface与interface之间的不同:
import java.lang.annotation.*; /** * 使用annotation来描述那些被标注的成员是不稳定的,需要更改 */ public @interface Unstable { } |
下面的另一个例子只定义了一个成员。并通过将这个成员命名为value,使我们可以方便的使用这种annotation的快捷声明方式:
/** * 使用Author这个annotation定义在程序中指出代码的作者 */ public @interface Author { /** 返回作者名 */ String value(); } |
以下的例子更加复杂。Reviews annotation类型只有一个成员,但是这个成员的类型是复杂的:由Review annotation组成的数组。Review annotation类型有3个成员:枚举类型成员grade、表示Review名称的字符串类型成员Reviewer、具有默认值的字符串类型成员 Comment。
/** * Reviews annotation类型只有一个成员, * 但是这个成员的类型是复杂的:由Review annotation组成的数组 */ @Retention(RetentionPolicy.RUNTIME) public @interface Reviews { Review[] value(); } /** * Review annotation类型有3个成员: * 枚举类型成员grade、 * 表示Review名称的字符串类型成员Reviewer、 * 具有默认值的字符串类型成员Comment。 */ public @interface Review { // 内嵌的枚举类型 public static enum Grade { EXCELLENT, SATISFACTORY, UNSATISFACTORY }; // 下面的方法定义了annotation的成员 Grade grade(); String reviewer(); String comment() default ""; } |
最后,我们来定义一个annotation方法用于罗列出类运行中所有的unchecked异常。这个 annotation类型将一个数组作为了唯一的成员。数组中的每个元素都是异常类。为了加强对未检查的异常(此类异常都是在运行时抛出)进行报告,我们可以在代码中对异常的类型进行限制:
public @interface UncheckedExceptions { Class<? extends RuntimeException>[] value(); } |
Meta-Annotation类型:
Annotation 类型可以被它们自己所标注。Java5.0定义了4个标准的meta-annotation类型,分别是:Target、Retention、Documented、Inherited,它们被用来提供对其它annotation类型作说明。 这些类型和它们所支持的类在java.lang.annotation包中可以找到。
@Target的用法:指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。例如,以下这个注释只能用来声明方法:
@Target(ElementType.METHOD) public @interface MyAnnotation { ... } |
java.lang.annotation.ElementType是一个枚举类型,它具有以下定义:
ElementType值 | 说明 |
ElementType.ANNOTATION_TYPE | 应用于注释类型声明 |
ElementType.CONSTRUCTOR | 构造方法声明 |
ElementType.FIELD | 应用于字段声明(包括枚举常量) |
ElementType.LOCAL_VARIABLE | 应用于局部变量声明 |
ElementType.METHOD | 应用于方法声明 |
ElementType.PACKAGE | 应用于包声明 |
ElementType.PARAMETER | 应用于参数声明 |
ElementType.TYPE | 应用于类、接口(包括注释类型)或枚举声明 |
@Retention的用法:指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS,例如:
@ Retention(RetentionPolicy.CLASS) public @interface MyAnnotation { ... } |
java.lang.annotation.RetentionPolicy是一个枚举类型,它具有以下定义:
RetentionPolicy值 | 说明 |
RetentionPolicy.CLASS | 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释 |
RetentionPolicy.RUNTIME | 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取 |
RetentionPolicy.SOURCE | 编译器要丢弃的注释 |
@Documented的用法:指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。Documented是一个没有成员的注释。
@Inherited的用法:指示注释类型自动被子类继承。 Inherited也是一个没有成员的注释。
注意,如果使用@Inherited注释类以外的任何事物都是无效的。还要注意,此元注释仅对从超类继承注释有效;对已实现接口的注释无效。
分享到:
相关推荐
JSF+Spring+Hibernate(Annotation)的login小实例,建议入门的朋友看看,老鸟就免了,呵呵。环境:SQLSever2000+jdk5.0+spring2.0+hibernate3.2+jsf
首先,我们来了解一下Java JDK 5.0。JDK(Java Development Kit)是Java编程环境的核心组成部分,包含了开发和运行Java应用程序所需的全部工具。JDK 5.0,又称为Java 5,是Java历史上的一个重要版本,于2004年发布。...
圣思园的Java课程不仅涵盖基础,还深入到JVM内核和字节码层面,讲解了JDK 5.0和6.0的新特性,并对并发包和集合框架的源代码进行了深度分析。此外,课程还包括单元测试,如JUnit的使用,这对于实际开发中的代码质量...
"良葛格java.jdk5.0学习笔记"中可能涵盖了这些内容,例如: 1. **类与对象**:Java中的万物皆为对象,类是创建对象的蓝图。笔记会详细介绍如何定义类,声明成员变量和方法,以及如何通过构造器初始化对象。 2. **...
JDK 5.0引入的新特性如泛型、枚举、可变参数、增强for循环和静态导入,显著提高了代码的可读性和复用性。Java Annotation允许我们在代码中添加元信息,自定义和使用系统内置的Annotation。Java多线程机制包括锁(如...
13.5 Spring对JDK 5.0 Executor的支持 13.5.1 了解JDK 5.0的Executor 13.5.2 Spring对Executor所提供的抽象 13.6 实际应用中的任务调度 13.6.1 如何产生任务 13.6.2 任务调度对应用程序集群的影响 13.6.3 任务调度云...
- **浪曦视频在线_风中叶_JDK5.0新特性**:介绍JAVA 5.0版本引入的新特性和改进,包括泛型、枚举等。 - **浪曦视频在线_风中叶_JavaAnnotation详解**:详细讲解了Java注解的使用方法及其应用场景。 #### J2EE基础 ...
13.5 Spring对JDK 5.0 Executor的支持 13.5.1 了解JDK 5.0的Executor 13.5.2 Spring对Executor所提供的抽象 13.6 实际应用中的任务调度 13.6.1 如何产生任务 13.6.2 任务调度对应用程序集群的影响 13.6.3 任务调度云...
1. JDK 5.0新特性:泛型、枚举、可变参数、增强的for循环和静态导入等。 2. Java Annotation:学习如何使用系统内置的注解,自定义注解以及注解的继承。 3. 多线程:深入理解Java的多线程机制,包括锁、synchronized...
JDK 5.0新特性:泛型提供类型安全,枚举替代常量,可变参数简化方法调用,增强的for循环简化迭代,静态导入减少代码冗余。 Annotation:用于元数据,可以帮助编译器和运行时环境提供信息。 多线程:Java提供了丰富...
首先,书中详细阐述了Java环境的搭建,包括如何下载JDK(Java Development Kit)以及设置环境变量,这是每个Java程序员入门的第一步。接下来,书中通过生动的实例引导读者了解如何编写和运行第一个"Hello, World!...
6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent collections) 7.2. 集合映射( Collection mappings ) 7.2.1. 集合外键(Collection foreign keys) 7.2.2. ...
15. **注解(Annotation)**:注解是Java SE 5.0引入的元数据,用于提供编译时和运行时的信息,如编译器警告、运行时验证等。 以上只是Java基础知识的一部分,实际的教材会通过实例和练习帮助初学者深入理解和应用...
Tiger是指Java 5.0版本(也称为JDK 1.5),这一版引入了许多新特性,例如泛型、注解(Annotation)、自动装箱等。这些新特性极大地提高了Java语言的表达能力和开发效率,是学习Java EE必须掌握的知识点。 XML学习...
Java程序设计基础教程是入门Java编程的绝佳资源,它涵盖了从基本语法到核心概念的全面讲解,旨在帮助初学者理解并掌握Java语言。本教程深入浅出地介绍了Java的各个方面,包括但不限于以下知识点: 1. **Java简介**...
5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) ...
使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent collections) 7.2. 集合映射( Collection mappings ) 7.2.1. 集合外键(Collection foreign keys) 7.2.2. 集合...