Java 注释
Java 注释提供有关代码的信息。Java 注释对其注释的代码没有直接影响。在 Java 注释教程中,我们将研究以下内容;
- 内置 Java 注释
- 如何编写自定义注释
- 注释的使用以及如何使用反射 API解析注释。
Java 注解
Java 1.5 引入了注解,现在它在 Hibernate、Jersey和Spring等 Java EE 框架中被广泛使用。Java 注解是嵌入在程序本身中的关于程序的元数据。它可以被注解解析工具或编译器解析。我们还可以指定注解仅在编译时或运行时可用。在 Java 注解出现之前,程序元数据可通过 Java 注释或 Javadoc 获取,但注解提供的不止这些。注解元数据在运行时也可用,注解解析器可以使用它来确定流程。例如,在Jersey webservice中,我们将带有 URI 字符串的 PATH 注解添加到方法,在运行时,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注释的一些要点是:
- 注释方法不能有参数。
- 注释方法的返回类型仅限于原语、字符串、枚举、注释或这些的数组。
- Java 注释方法可以有默认值。
- 注释可以附加元注释。元注释用于提供有关注释的信息。
Java 中的元注释
元注释有五种类型:
- @Documented - 表示使用此注释的元素应由 javadoc 和类似工具记录。此类型应用于注释类型的声明,这些类型的注释会影响其客户端对注释元素的使用。如果类型声明使用 Documented 注释,则其注释将成为注释元素的公共 API 的一部分。
- @Target - 表示注释类型适用的程序元素种类。一些可能的值是 TYPE、METHOD、CONSTRUCTOR、FIELD 等。如果不存在 Target 元注释,则可以在任何程序元素上使用注释。
- @Inherited - indicates that an annotation type is automatically inherited. If user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class’s superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached.
- @Retention - indicates how long annotations with the annotated type are to be retained. It takes RetentionPolicy argument whose Possible values are SOURCE, CLASS and RUNTIME
- @Repeatable - used to indicate that the annotation type whose declaration it annotates is repeatable.
Built-in annotations in Java
Java Provides five built-in annotations.
@Override
- When we want to override a method of Superclass, we should use this annotation to inform compiler that we are overriding a method. So when superclass method is removed or changed, compiler will show error message. Learn why we should always use java override annotation while overriding a method.@Deprecated
- when we want the compiler to know that a method is deprecated, we should use this annotation. Java recommends that in javadoc, we should provide information for why this method is deprecated and what is the alternative to use.@SuppressWarnings
- This is just to tell compiler to ignore specific warnings they produce, for example using raw types in java generics. It’s retention policy is SOURCE and it gets discarded by compiler.@FunctionalInterface
- This annotation was introduced in Java 8 to indicate that the interface is intended to be a functional interface.@SafeVarargs
- A programmer assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter.
Java Annotations Example
Let’s see a java example showing the use of built-in annotations in java as well as the use of custom annotation created by us in the above example.
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 Annotations Parsing
We will use Reflection to parse java annotations from a class. Please note that Annotation Retention Policy should be RUNTIME otherwise its information will not be available at runtime and we won’t be able to fetch any data from it.
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()) {
// checks if MethodInfo annotation is present for the method
if (method.isAnnotationPresent(com.journaldev.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();
}
}
}
Output of the above program is:
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 is very powerful and used widely in Java, J2EE frameworks like Spring, Hibernate, JUnit, check out Reflection in Java. That’s all for the java annotations example tutorial, I hope you learned something from it. Java Annotations Updates:
- Servlet Specs 3.0 引入了对 Servlet 配置和初始化参数的注释的使用,有关详细信息,请参阅Java Servlet 教程。
- 我们可以在 Struts 2 中使用注释来配置它的动作类和结果页面,请查看Struts 2 Hello World 注释示例中的工作示例。
参考:Oracle 网站