Java注释

时间:2020-02-23 14:36:20  来源:igfitidea点击:

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

  • 内置Java注释
  • 如何编写自定义注释
  • 注释用法以及如何使用Reflection API解析注释。

Java注解

Java 1.5引入了注释,现在它已在Hibernate,Jersey和Spring等Java EE框架中大量使用。

Java注释是有关嵌入在程序本身中的程序的元数据。
可以通过注释解析工具或者编译器进行解析。
我们还可以指定注释可用性以仅编译时间或者直到运行时。

在使用Java批注之前,程序元数据可通过Java注释或者Javadoc获得,但批注提供的功能更多。
注释元数据也可以在运行时使用,注释解析器可以使用它来确定流程。

例如,在Jersey网络服务中,我们将带有URI字符串的PATH注释添加到方法中,并且在运行时,jersey对其进行解析,以确定要为给定URI模式调用的方法。

Java自定义注释

创建自定义批注与编写接口相似,不同之处在于interface关键字的前缀是@符号。
我们可以在注解中声明方法。

让我们看一下Java自定义注释示例,然后我们将讨论其功能和要点。

package com.theitroad.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 "hyman";
	String date();
	int revision() default 1;
	String comments();
}

关于Java注释的一些重要点是:

  • 注释方法不能包含参数。

  • 注释方法的返回类型仅限于原语,字符串,枚举,注释或者它们的数组。

  • Java注释方法可以具有默认值。

  • 批注可以附加元批注。
    元注释用于提供有关注释的信息。

Java中的元注释

元注释有五种类型:

  • @Documented –指示使用此注释的元素应由javadoc和类似工具记录。
    此类型应用于注释类型的声明,这些类型的注释会影响其客户端对已注释元素的使用。
    如果类型声明用Documented进行注释,则其注释将成为带注释元素的公共API的一部分。

  • @Target –指示注释类型适用的程序元素的种类。
    一些可能的值是TYPE,METHOD,CONSTRUCTOR,FIELD等。
    如果没有Target元注释,则可以在任何程序元素上使用注释。

  • @Inherited –表示注释类型是自动继承的。
    如果用户在类声明中查询注释类型,并且该类声明没有该类型的注释,则将自动查询该类的超类以获取注释类型。
    重复此过程,直到找到该类型的注释,或者到达类层次结构(对象)的顶部为止。

  • @Retention –指示带注释类型的注释将保留多长时间。
    它采用RetentionPolicy参数,其可能值为SOURCE,CLASS和RUNTIME

  • @Repeatable –用于指示其注释的注释的注释类型是可重复的。

Java内置注释

Java提供五个内置注释。

  • @ Override–当我们想重写一个超类的方法时,我们应该使用这个注释来通知编译器我们正在重写一个方法。
    因此,当删除或者更改超类方法时,编译器将显示错误消息。
    了解为什么我们在覆盖方法时总是应该使用Java覆盖注释。

  • @ Deprecated–当我们希望编译器知道某个方法已被弃用时,我们应该使用此注释。
    Java建议在javadoc中,我们应提供有关为什么不赞成使用此方法以及可以使用什么替代方法的信息。

  • @SuppressWarnings-只是告诉编译器忽略它们产生的特定警告,例如在Java泛型中使用原始类型。
    它的保留政策是SOURCE,编译器会丢弃它。

  • @ FunctionalInterface-Java 8中引入了此批注,以指示该接口旨在用作功能接口。

  • @SafeVarargs-程序员断言带注释的方法或者构造函数的主体不会对其varargs参数执行潜在的不安全操作。

Java注释示例

让我们看一个Java示例,该示例显示在Java中使用内置注释以及在上述示例中由我们创建的自定义注释的使用。

package com.theitroad.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 = "hyman", 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 = "hyman", comments = "Main method", date = "Nov 17 2012", revision = 10)
	public static void genericsTest() throws FileNotFoundException {
		List l = new ArrayList();
		l.add("abc");
		oldMethod();
	}

}

我相信上面的Java注释示例是不言自明的,并显示了在不同情况下使用注释的情况。

Java注解解析

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

package com.theitroad.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.theitroad.annotations.AnnotationExample")).getMethods()) {
				//checks if MethodInfo annotation is present for the method
				if (method.isAnnotationPresent(com.theitroad.annotations.MethodInfo.class)) {
					try {
						//iterates all the annotations available in the method
						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.theitroad.annotations.AnnotationExample.toString()' : @com.theitroad.annotations.MethodInfo(author=hyman, revision=1, comments=Main method, date=Nov 17 2012)
Method with revision no 1 = public java.lang.String com.theitroad.annotations.AnnotationExample.toString()
Annotation in Method 'public static void com.theitroad.annotations.AnnotationExample.oldMethod()' : @java.lang.Deprecated()
Annotation in Method 'public static void com.theitroad.annotations.AnnotationExample.oldMethod()' : @com.theitroad.annotations.MethodInfo(author=hyman, revision=1, comments=deprecated method, date=Nov 17 2012)
Method with revision no 1 = public static void com.theitroad.annotations.AnnotationExample.oldMethod()
Annotation in Method 'public static void com.theitroad.annotations.AnnotationExample.genericsTest() throws java.io.FileNotFoundException' : @com.theitroad.annotations.MethodInfo(author=hyman, revision=10, comments=Main method, date=Nov 17 2012)