??Java的注解在學習框架的時候很常見,一般配置信息都可以通過配置文件和注解兩種方式進行配置,所以最近小碼農(nóng)就大致學習了一下注解。
注解的作用
??首先,注解是和類、接口同一層次的東西。它是那些插入到源代碼中并且使用其他工具可以對其進行處理的標簽。常見的注解都是@xxx的形式。那么具體的來說,注解常用來干什么呢?
- 代碼分析:對代碼進行分析,可以取代xml文檔,即配置信息。
- 編譯檢查:讓編譯器實現(xiàn)基本的編譯檢查。例如:@Override
- 編寫文檔:輔助生成解釋文檔。如HTML文件。
輔助生成解釋文檔
??按照小碼農(nóng)寫文章的習慣,重要的知識寫在前面,但分析的時候從后向前分析。所以我們先來看看第一個:生成解釋文檔。
??不知道大家在寫注釋的時候是否注意到一般作者前使用@author,版本號之前使用@since。乍一看,是不是這個就和注解的格式一樣呢?而實際上,它們確實和注解有關聯(lián),在注釋中標識注解能輔助我們生成解釋文檔,看一個小例子。
??為了方便,我們直接把Object類的注釋拿來放在我們測試類頭上。
/**
* Class {@code Object} is the root of the class hierarchy.
* Every class has {@code Object} as a superclass. All objects,
* including arrays, implement the methods of this class.
*
* @author unascribed
* @see java.lang.Class
* @since JDK1.0
*/
public class First {
public static void main(String[] args) {
}
}
??點擊Project -> Generation,選擇javadoc command為JDK中的javadoc.exe。然后一直next到最后一頁(為了防止出現(xiàn):編碼GBK的不可映射字符的錯誤)在 VM options...下的空格里寫入-encoding UTF-8 -charset UTF-8。然后點擊Finish就可以把注釋導出成HTML文件。


??不過,它里面的注釋也不是亂寫的,比如你有一個@date,但這個標識不是默認的,生成HTML文檔時會出現(xiàn)“未知標記: date”錯誤,這時候需要在導出時配置一下。也是在最后一頁,Extra Javadoc options...下的空里加上“-tag date:a:日期”就可以了,它的語法是:-tag 注釋中寫的標簽:a:文檔中的標簽 。

元注解&屬性
??在學注解的其他作用時,我們先來看看幾個注解的注解,也就是寫在注解上的注解。注解和類、接口處在同一層次,自然也可以自定義,自定義的時候?qū)ψ⒔庖部梢约由献⒔猓@些能加在注解上的注解被叫做元注解。

??以上的元注解便是這個注解是源碼級別的。元注解共有四個,如下:
- @Retention():確定被修飾的自定義注解的生命周期。
- @Target():確定被被修飾的自定義注解的使用位置。
- @Documented:使用javadoc生成文檔需要包含此注解。
- @Inherited:被修飾的子類繼承父類的注解。
??屬性就是我們在圓括號里加入的說明語句,用來說明這個注解的某些性質(zhì)。
| 元注解 | 屬性 |
|---|---|
| @Retention() | RetentionPolicy.XXX SOURCE、CLASS、RUNTIME |
| @Target() | ElementType.XXX TYPE、FIELD、METHOD、PARAMETER、PACKAGE、 LOCAL_VARIABLE、ANNOTATION_TYPE、CONSTRUCTOR、TYPE_PARAMETER、TYPE_USE |
編譯檢查
??第二點是幫助我們進行基本的編譯檢查,這個就很簡單了,如@Override、@Deprecated、@SuppressWarnings等都是JDK提給我們的編譯檢查的注解,我們當然也可以自定義編譯檢查注解,不過不常用而且挺麻煩,所以在這省去。
代碼分析
??第三點就是代碼分析,這個主要用到反射的技術。接下來先看看注解的語法:
modifiers @interface AnnotationName{
elementDeclaration1
elementDeclaration2
...
}
其中元素聲明必須是 type elementName(); 格式如下例:
public @interface MyAnnotation{
boolean isTrue() defalut false;
String[] strs();
}
??注解只是一個標簽,所以我們要使用反射獲取信息,必須創(chuàng)建一個類,在此類中使用反射獲取我們想要的信息再執(zhí)行。
??先定義一個注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyFirstAno {
String name() default "";
}
??再寫一個測試類:
public class TestMyFirstAno {
@MyFirstAno(name="詹金浩")
public void show(String str) {
System.out.println("this is " + str + "...");
}
}
??再反射執(zhí)行
public class MyFirstAnoParser {
public static void main(String[] args) throws Exception {
Class<TestMyFirstAno> clazz = TestMyFirstAno.class;
Method method = clazz.getMethod("show", String.class);
MyFirstAno ano = method.getAnnotation(MyFirstAno.class);
String name = ano.name();
Constructor<TestMyFirstAno> constructor = clazz.getConstructor();
TestMyFirstAno instance = constructor.newInstance();
method.invoke(instance, name); //Console : this is 詹金浩...
}
}
??對于Java EE碼農(nóng)來說,注解只要會用就可以了,所以本文只做淺要分析。