Java Annotations 提供有关代码的信息。Java 注解对其注释的代码没有直接影响。在 Java 注解教程中,我们将研究以下内容:
- 内置 Java 注解
- 如何编写自定义注解
- 注解的使用以及如何使用 Reflection API 解析注解。
Java 注解
Java 1.5引入了注解,现在在Java EE框架中广泛使用,如Hibernate,Jersey和Spring。Java注解是嵌入在程序中的有关程序的元数据。它可以由注解解析工具或编译器解析。我们还可以指定注解的可用性,要么只在编译时,要么在运行时。在Java注解之前,程序元数据可以通过Java注释或Javadoc获得,但注解提供的功能更多。注解元数据也可以在运行时获得,注解解析器可以使用它来确定流程。例如,在Jersey web服务中,我们将路径注解与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 註釋的一些重要要點:
- 註釋方法不能具有參數。
- 註釋方法的返回類型僅限於基本類型、字符串、枚舉、註釋或這些類型的數組。
- Java 註釋方法可以具有默認值。
- 註釋可以附加元註釋。元註釋用於提供有關註釋的信息。
Java 中的元註釋
有五種類型的元註釋:
- @Documented – 表示使用此註釋的元素應該由 javadoc 和類似工具進行文檔化。應該使用此類型來注釋那些其註釋影響客戶端使用的元素的聲明類型。如果一個類型聲明被註釋為 Documented,則其註釋將成為被註釋元素的公共 API 的一部分。
- @目標 – 標示注釋類型適用於哪種程式元素。一些可能的值包括TYPE、METHOD、CONSTRUCTOR、FIELD等。如果未出現Target元注釋,則該注釋可用於任何程式元素。
- @Inherited – 表示注釋類型會自動繼承。如果用戶在類聲明上查詢注釋類型,且該類聲明對此類型沒有注釋,則將自動查詢該類的超類以獲取該類型的注釋。此過程將重複進行,直到找到該類型的注釋,或達到類層次結構的頂部(Object)。
- @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.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 注釋解析
我們將使用反射來解析 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)
反射 API 非常強大,在 Java、J2EE 框架如 Spring、Hibernate、JUnit 中被廣泛使用,請查看 Java 中的反射。這就是 Java 注釋範例教程的全部內容,希望你從中學到了一些東西。Java 注釋更新:
- Servlet Specs 3.0 引入了使用註解進行 Servlet 配置和初始化參數,詳細資訊請參閱Java Servlet 教程。
- 我們可以在 Struts 2 中使用註解來配置其動作類別和結果頁面,可在Struts 2 Hello World Annotation Example中查看工作範例。
參考: Oracle 網站
Source:
https://www.digitalocean.com/community/tutorials/java-annotations