Java Annotations 注解
注解简介
注解是一种元数据形式,提供有关不属于程序本身的程序的数据。注解对他们注解的代码的操作没有直接影响。
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
注解的作用:
- 编译器的信息:编译器可以使用注解来检测错误或取消警告。
- 编译时和部署时处理:软件工具可以处理注解信息以生成代码,XML文件等等
- 运行时处理:一些注解可用于在运行时检查。
注解的类型
java.lang包中的预定义注解(predefined annotation)
@Deprecated:表示标记的元素已弃用,不应再使用.
只要程序使用具有@Deprecated注解的方法,类或字段,编译器就会生成警告。
@Override:
通知编译器该元素意味着覆盖在超类中声明的元素虽然在重写方法时不需要使用此注解,但它有助于防止错误。如果使用@Override标记的方法无法正确覆盖其超类中的某个方法,则编译器会生成一个错误。
@SuppressWarnings
注解告诉编译器禁止它会产生的特定警告,例如:使用了不推荐使用的方法,编译器通常会生成警告,此时使用SuppressWarnings注解会导致警告被抑制。每个编译器警告都属于一个类别。Java语言规范列出了两个类别:弃用(deprecation )和未选中(unchecked).当与泛型出现之前编写的遗留代码实现接口时,可能会发生未经检查的警告。要禁止多个类别的警告,请使用以下语法:@SuppressWarnings({“unchecked”, “deprecation”})
@SafeVarargs
当应用于方法或构造函数时,声明代码不会对其可变参数参数执行潜在的不安全操作。当使用这种注解类型时,与可变参数使用有关的未经检查的警告被抑制。
@FunctionalInterface
表示类型声明旨在成为Java语言规范定义的函数式接口(只含有一个抽象方法的接口)
java.lang.annotation包中的元注解(meta-annotations)
用于其它注解的注解叫元注解(Annotations that apply to other annotations are called meta-annotations).
@Retention:指定标记注解的存储方式
- RetentionPolicy.SOURCE:标记的注解仅保留在源代码级别,并且被编译器忽略。
- RetentionPolicy.CLASS:标记的注解在编译时由编译器保留,但被Java虚拟机(JVM)忽略,
- RetentionPolicy.RUNTIME:标记的注解由JVM保留,因此它可以被运行时环境使用
@Documented:表示无论何时使用指定的注解,都应该使用Javadoc工具来记录这些元素。
@Target:标记另一个注解来限制注解可以应用于什么类型的Java元素。
- ElementType.ANNOTATION_TYPE :可以应用于注释类型
- ElementType.CONSTRUCTOR:可以应用于构造函数.
- ElementType.FIELD :可以应用于某个字段
- ElementType.LOCAL_VARIABLE:可以应用于局部变量.
- ElementType.METHOD 可以应用于方法级别的注解.
- ElementType.PACKAGE 可以应用于包级别的注解.。
- ElementType.PARAMETER 可以应用于方法的参数。
- ElementType.TYPE 可以应用于任何类的元素.
@Inherited:表示注解可以从超类继承
默认情况下不是这样。当用户查询注解类型并且类没有这种类型的注解时,查询类的超类的注解类型类型。此注解仅适用于类声明。
@Repeatable:表示标记的注解可以多次应用于相同的声明或类型使用。
java8中的注解
在Java SE 8之前,注解只能应用于声明。从Java SE 8开始,注解也可以应用于任何类型的用途。这意味着可以在使用类型的任何地方使用注解。例如:@NonNull String str;
例子
Runtime Method
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation1 {
String name() default "注解1";
}
public class Annotation1Processor {
public void parseAnnotation1(final Class<?> clazz) throws Exception {
final Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
final Method[] methods = clazz.getDeclaredMethods();
for (final Method method : methods) {
final Annotation1 my = method.getAnnotation(Annotation1.class);
if (null != my) {
method.invoke(obj, my.name());
}
}
}
}
public class TestAnnotation1 {
public static void main(String[] args) throws Exception{
test();
}
private static void test() throws Exception {
Annotation1Processor annoProcessor=new Annotation1Processor();
annoProcessor.parseAnnotation1(TestAnnotation1.class);
}
/**
* 注解 通过反射调用此方法
* @param name
*/
@Annotation1
public static void test1(final String name) {
System.out.println("==>> Hi, " + name + " [sayHello]");
}
/**
* 注解 通过反射调用此方法
* @param name
*/
@Annotation1(name = "AngelaBaby")
public static void test2(final String name) {
System.out.println("==>> Hi, " + name + " [sayHelloToSomeone]");
}
}
//输出
==>> Hi, AngelaBaby [sayHelloToSomeone]
==>> Hi, 注解1 [sayHello]