Java注解

Java注解提供了有关代码的信息。 Java注解对其注解的代码没有直接影响。 在Java注解教程中,我们将查看以下内容;

  1. 内置Java注解
  2. 如何编写自定义注解
  3. 注解用法以及如何使用反射API解析注解。

Java注解

Java 1.5 引入了注解,现在在 Java EE 框架中(如 Hibernate、Jersey 和 Spring)被广泛使用。Java 注解是嵌入在程序本身中的程序元数据。它可以被注解解析工具或编译器解析。我们还可以指定注解的可用性,可以是仅在编译时或一直到运行时。在 Java 注解之前,程序元数据是通过 Java 注释或 Javadoc 提供的,但注解提供的功能更多。注解元数据也可以在运行时可用,并且注解解析器可以使用它来确定处理流程。例如,在 Jersey web 服务中,我们将 PATH 注解与 URI 字符串添加到方法中,在运行时,Jersey 解析它以确定为给定 URI 模式调用的方法。

Java 自定义注解

创建自定义注解类似于编写接口,只是接口关键字前缀加上_@_符号。我们可以在注解中声明方法。让我们看一个Java自定义注解的例子,然后我们将讨论其特点和重要点。

package com.journaldev.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo{
	String author() default "Pankaj";
	String date();
	int revision() default 1;
	String comments();
}

关于Java注解的一些重要点如下:

  1. 注解方法不能带参数。
  2. 注解方法的返回类型仅限于基本类型、字符串、枚举、注解或这些类型的数组。
  3. Java注解方法可以具有默认值。
  4. 注解可以附加元注解。元注解用于提供有关注解的信息。

Java中的元注解

有五种类型的元注解:

  1. @Documented – 表示使用此注解的元素应该由javadoc和类似工具记录。此类型应该用于注解那些通过其客户端使用的注解元素的类型声明。如果类型声明被注解为Documented,则其注解将成为被注解元素的公共API的一部分。
  2. @Target – 指示注解类型可适用于哪些程序元素。一些可能的值是TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解不存在,则注解可以用于任何程序元素。
  3. @Inherited – 表示注解类型会自动继承。如果用户在类声明上查询注解类型,并且该类声明没有此类型的注解,则该类的超类将自动查询注解类型。此过程将重复进行,直到找到此类型的注解,或者达到类层次结构(Object)的顶部。
  4. @Retention – 表示带有注解类型的注解将被保留多长时间。它接受RetentionPolicy参数,其可能的值为SOURCE,CLASS和RUNTIME
  5. @Repeatable – 用于指示其声明注释类型是可重复的注释类型。

Java中的内置注释

Java提供了五种内置注释。

  1. @Override – 当我们想要重写超类的方法时,应使用此注解通知编译器我们正在重写一个方法。因此,当超类方法被移除或更改时,编译器将显示错误消息。了解为什么在重写方法时应始终使用Java重写注解
  2. @Deprecated – 当我们希望编译器知道某个方法已被弃用时,应使用此注解。Java建议在javadoc中提供有关为何此方法已被弃用以及替代方法的信息。
  3. @SuppressWarnings – 这只是告诉编译器忽略它们产生的特定警告,例如在Java泛型中使用原始类型。它的保留策略是SOURCE,会被编译器丢弃。
  4. @FunctionalInterface – 此注解是在Java 8中引入的,用于指示该接口意图成为一个函数式接口
  5. @SafeVarargs – 程序员断言,带有此注解的方法或构造函数的主体不对其可变参数执行潜在不安全的操作。

Java注解示例

让我们看一个Java示例,展示了在Java中使用内置注解以及在上述示例中我们创建的自定义注解的用法。

package com.journaldev.annotations;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class AnnotationExample {

	public static void main(String[] args) {
	}

	@Override
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 1)
	public String toString() {
		return "Overriden toString method";
	}

	@Deprecated
	@MethodInfo(comments = "deprecated method", date = "Nov 17 2012")
	public static void oldMethod() {
		System.out.println("old method, don't use it.");
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 10)
	public static void genericsTest() throws FileNotFoundException {
		List l = new ArrayList();
		l.add("abc");
		oldMethod();
	}

}

I believe above java annotation example is self-explanatory and showing the use of annotations in different cases.

Java注解解析

我们将使用反射(Reflection)来解析Java类中的注解。请注意,注解的保留策略应为RUNTIME,否则其信息在运行时将不可用,我们将无法从中提取任何数据。

package com.journaldev.annotations;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class AnnotationParsing {

	public static void main(String[] args) {
		try {
			for (Method method : AnnotationParsing.class.getClassLoader()
					.loadClass(("com.journaldev.annotations.AnnotationExample")).getMethods()) {
				// 检查方法是否存在MethodInfo注解
				if (method.isAnnotationPresent(com.journaldev.annotations.MethodInfo.class)) {
					try {
						// 迭代方法中所有可用的注解
						for (Annotation anno : method.getDeclaredAnnotations()) {
							System.out.println("Annotation in Method '" + method + "' : " + anno);
						}
						MethodInfo methodAnno = method.getAnnotation(MethodInfo.class);
						if (methodAnno.revision() == 1) {
							System.out.println("Method with revision no 1 = " + method);
						}

					} catch (Throwable ex) {
						ex.printStackTrace();
					}
				}
			}
		} catch (SecurityException | ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}

以上程序的输出是:

Annotation in Method 'public java.lang.String com.journaldev.annotations.AnnotationExample.toString()' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=1, comments=Main method, date=Nov 17 2012)
Method with revision no 1 = public java.lang.String com.journaldev.annotations.AnnotationExample.toString()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.oldMethod()' : @java.lang.Deprecated()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.oldMethod()' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=1, comments=deprecated method, date=Nov 17 2012)
Method with revision no 1 = public static void com.journaldev.annotations.AnnotationExample.oldMethod()
Annotation in Method 'public static void com.journaldev.annotations.AnnotationExample.genericsTest() throws java.io.FileNotFoundException' : @com.journaldev.annotations.MethodInfo(author=Pankaj, revision=10, comments=Main method, date=Nov 17 2012)

Reflection API非常强大,在Java、J2EE框架(如Spring、Hibernate)、JUnit等广泛使用,请查看Java中的反射。这就是关于Java注解示例教程的全部内容,希望您从中学到了一些东西。Java注解更新

  1. Servlet Specs 3.0 引入了注解来配置 Servlet 和 init 参数,更多内容请阅读Java Servlet 教程
  2. 我们可以在 Struts 2 中使用注解来配置其动作类和结果页面,查看工作示例请访问Struts 2 你好世界 注解示例

参考:Oracle 网站

Source:
https://www.digitalocean.com/community/tutorials/java-annotations