Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件、或者运行时中出现(SOURCE/CLASS/RUNTIME)。
常用内置注解
@Override
对覆盖超类中方法的方法进行标记,如果被标记的类并没有实际覆盖超类,则编译器会发出错误警告。
@Override源码
/*
* %W% %E%
*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
import java.lang.annotation.*;
/**
* Indicates that a method declaration is intended to override a
* method declaration in a superclass. If a method is annotated with
* this annotation type but does not override a superclass method,
* compilers are required to generate an error message.
*
* @author Joshua Bloch
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Override示例
public class Test
{
@Override
public String toString()
{
return super.toString();
}
}
@Deprecated
它的作用是对不应该再使用的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息。
@Deprecated源码
/*
* %W% %E%
*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
import java.lang.annotation.*;
/**
* A program element annotated @Deprecated is one that programmers
* are discouraged from using, typically because it is dangerous,
* or because a better alternative exists. Compilers warn when a
* deprecated program element is used or overridden in non-deprecated code.
*
* @author Neal Gafter
* @version %I%, %G%
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}
@Deprecated示例
public class Test
{
@Deprecated
public void deprecated()
{
}
}
自定义注解
注解的定义类似于新创建一个接口类文件,但为了区分,我们需要将它声明为@interface,如下例:
public @interface NewAnnotation {
}
在自定义注解的时候,我们最常用的内置元注解有如下几个:
- @Target
指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。 例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上:
@Target(ElementType.ANNOTATION_TYPE)
public @interface MetaAnnotationType {
}
此元注释指示该声明类型只可作为复杂注释类型声明中的成员类型使用。它不能直接用于注释:
@Target({})
public @interface MemberType {
}
这是一个编译时错误,它表明一个 ElementType 常量在 Target 注释中出现了不只一次。例如,以下元注释是非法的:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
public @interface Bogus {
}
- @Retention
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
- 举个例子:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation
{
}
上面我们定义了一个用于类上面的注解,且该注解在运行时有效。我们可以这样使用注解:
@ClassAnnotation
public class AnnotationTest
{
public static void main(String[] args)
{
Class<AnnotationTest> clazz = AnnotationTest.class;
if (clazz.isAnnotationPresent(ClassAnnotation.class))
{
System.out.println("存在@ClassAnnotation注解");
}
}
}
这只是一个简单的例子,我们还可以用注解做很多事,例如我们可以向注解中添加元数据,修改上面的示例:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation
{
String value();
String memo() default "";
}
继续改写我们的测试代码:
@ClassAnnotation(value = "ClassAnnotation", memo = "ClassAnnotation test")
public class AnnotationTest
{
public static void main(String[] args)
{
Class<AnnotationTest> clazz = AnnotationTest.class;
if (clazz.isAnnotationPresent(ClassAnnotation.class))
{
System.out.println("存在@ClassAnnotation注解");
ClassAnnotation annotation = clazz
.getAnnotation(ClassAnnotation.class);
System.out.println("value:" + annotation.value());
System.out.println("memo:" + annotation.memo());
}
}
}
需要注意的是,当我们为注解赋值时,如果仅对value
进行赋值,可以直接赋值,类似如下形式:
@ClassAnnotation("ClassAnnotation")
public class AnnotationTest
{
public static void main(String[] args)
{
Class<AnnotationTest> clazz = AnnotationTest.class;
if (clazz.isAnnotationPresent(ClassAnnotation.class))
{
System.out.println("存在@ClassAnnotation注解");
ClassAnnotation annotation = clazz
.getAnnotation(ClassAnnotation.class);
System.out.println("value:" + annotation.value());
System.out.println("memo:" + annotation.memo());
}
}
}