Java Annotations
Java Annotations提供有关代码的信息。Java注释对它们注释的代码没有直接影响。在java annotations教程中,我们将研究以下内容:
- 内置Java注释
- 如何编写自定义注释
- 注释用法以及如何使用Reflection API解析注释。
目录[ 隐藏 ]
Java注释
Java 1.5引入了注释,现在它大量用于Java EE框架,如Hibernate,Jersey和Spring。
Java Annotation是有关程序本身嵌入的程序的元数据。它可以由注释解析工具或编译器解析。我们还可以将注释可用性指定为仅编译时间或直到运行时。
在Java注释之前,程序元数据可以通过Java注释或Javadoc获得,但是注释提供了更多。注释元数据也可以在运行时使用,注释解析器可以使用它来确定流程。
例如,在Jersey webservice中,我们将带有URI字符串的PATH注释添加到方法中,并且在运行时,jersey会解析它以确定为给定URI模式调用的方法。
Java自定义注释
创建自定义注释与编写接口类似,只是interface关键字以@符号为前缀。我们可以在注释中声明方法。
让我们看一下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 Annotation方法可以具有默认值。
- 注释可以附加元注释。元注释用于提供有关注释的信息。
java中的元注释
元注释有五种类型:
- @Documented - 表示使用此注释的元素应由javadoc和类似工具记录。此类型应用于注释类型的声明,其注释会影响客户端对带注释元素的使用。如果使用Documented注释类型声明,则其注释将成为带注释元素的公共API的一部分。
- @Target - 表示注释类型适用的程序元素的种类。一些可能的值是TYPE,METHOD,CONSTRUCTOR,FIELD等。如果不存在Target元注释,则可以在任何程序元素上使用注释。
- @Inherited - 表示自动继承注释类型。如果用户在类声明上查询注释类型,并且类声明没有此类型的注释,则将自动查询类的超类以获取注释类型。将重复此过程,直到找到此类型的注释,或者到达类层次结构(对象)的顶部。
- @Retention - 表示要保留带注释类型的注释的时间长度。它需要RetentionPolicy参数,其可能值为SOURCE,CLASS和RUNTIME
- @Repeatable - 用于指示其注释声明的注释类型是可重复的。
Java中的内置注释
Java提供五个内置注释。
@Override
- 当我们想要覆盖Superclass的方法时,我们应该使用这个注释来通知编译器我们正在覆盖一个方法。因此,当删除或更改超类方法时,编译器将显示错误消息。了解为什么我们应该在覆盖方法时始终使用java覆盖注释。@Deprecated
- 当我们希望编译器知道某个方法已被弃用时,我们应该使用这个注释。Java建议在javadoc中,我们应该提供有关不推荐使用此方法的原因的信息以及使用的替代方法。@SuppressWarnings
- 这只是告诉编译器忽略它们产生的特定警告,例如使用java泛型中的原始类型。它的保留策略是SOURCE,它会被编译器丢弃。@FunctionalInterface
- 这个注释是在Java 8中引入的,表明该接口旨在成为一个功能接口。@SafeVarargs
- 程序员断言,带注释的方法或构造函数的主体不对其varargs参数执行可能不安全的操作。
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();
}
}
我相信上面的java注释示例是不言自明的,并显示了在不同情况下使用注释。
Java Annotations Parsing
我们将使用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()) {
// 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();
}
}
}
上述计划的输出是:
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中的Reflection。
这就是java注释示例教程的全部内容,我希望您从中学到了一些东西。
Java注释更新:
- Servlet规范3.0引入了对Servlet配置和init参数的注释的使用,请阅读Java Servlet教程。
- 我们可以在Struts 2中使用注释来配置它的动作类和结果页面,请查看Struts 2 Hello World Annotation示例中的工作示例。
PS: 本文中的注释,指注解,因为从文学角度上讲注释和注解一样大致相同,因为在程序语言中注释有单独意义,故此说明。