深入學習JAVA註解-Annotation(學習過程)
- * The method does override or implement a method declared in a * supertype. *
- * The method has a signature that is override-equivalent to that of * any public method declared in {@linkplain Object}. *
As a matter of style, programmers should always use this annotation * on the most deeply nested element where it is effective. If you want to * suppress a warning in a particular method, you should annotate that * method rather than its class. * * @author Josh Bloch * @since 1.5 * @jls 4.8 Raw Types * @jls 4.12.2 Variables of Reference Type * @jls 5.1.9 Unchecked Conversion * @jls 5.5.2 Checked Casts and Unchecked Casts * @jls 9.6.3.5 @SuppressWarnings */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { /** * The set of warnings that are to be suppressed by the compiler in the * annotated element. Duplicate names are permitted. The second and * successive occurrences of a name are ignored. The presence of * unrecognized warning names is not an error: Compilers must * ignore any warning names they do not recognize. They are, however, * free to emit a warning if an annotation contains an unrecognized * warning name. * *
The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
```
它有一個 value 屬性需要你主動的傳值,這個 value 代表一個什麼意思呢,這個 value 代表的就是需要被壓制的警告型別。例如:
```
public static void main(String[] args) {
Date date = new Date(2019, 12, 27);
}
```
這麼一段程式碼,程式啟動時編譯器會報一個警告。
> Warning:(8, 21) java: java.util.Date 中的 Date(int,int,int) 已過時
而如果我們不希望程式啟動時,編譯器檢查程式碼中過時的方法,就可以使用 @SuppressWarnings 註解並給它的 value 屬性傳入一個引數值來壓制編譯器的檢查。
```
@SuppressWarning(value = "deprecated")
public static void main(String[] args) {
Date date = new Date(2019, 12, 27);
}
```
這樣你就會發現,編譯器不再檢查 main 方法下是否有過時的方法呼叫,也就壓制了編譯器對於這種警告的檢查。
當然,JAVA 中還有很多的警告型別,他們都會對應一個字串,通過設定 value 屬性的值即可壓制對於這一類警告型別的檢查。
### 自定義註解:
自定義註解的語法比較簡單,通過類似以下的語法即可自定義一個註解。
```
public @interface InnotationName{
}
```
> 當然,自定義註解的時候也可以選擇性的使用元註解進行修飾,這樣你可以更加具體的指定你的註解的生命週期、作用範圍等資訊。
### 註解的屬性 && 註解的使用
註解的屬性也叫做成員變數。註解只有成員變數,沒有方法。註解的成員變數在註解的定義中以“無形參的方法”形式來宣告,其方法名定義了該成員變數的名字,其返回值定義了該成員變數的型別。
```
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id();
String msg();
}
```
上面程式碼定義了 TestAnnotation 這個註解中擁有 id 和 msg 兩個屬性。在使用的時候,我們應該給它們進行賦值。
賦值的方式是在註解的括號內以 value=”” 形式,多個屬性之前用 ,隔開。
需要注意的是,在註解中定義屬性時它的型別必須是 8 種基本資料型別外加 類、介面、註解及它們的陣列。
註解中屬性可以有預設值,預設值需要用 default 關鍵值指定。比如:
```
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public int id() default -1;
public String msg() default "Hi";
}
```
TestAnnotation 中 id 屬性預設值為 -1,msg 屬性預設值為 Hi。 **它可以這樣應用。**
```
@TestAnnotation()
public class Test {}
```
因為有預設值,所以無需要再在 @TestAnnotation 後面的括號裡面進行賦值了,這一步可以省略。
最後,還需要注意的一種情況是一個註解沒有任何屬性。比如
```
public @interface Perform {}
```
那麼在應用這個註解的時候,括號都可以省略。
---
#### 到目前為止:我僅僅知道註解是如何定義的,具體用起來是怎麼實現的呢?
1. 比如@override是怎麼去校驗的??畢竟點開原始碼,看它定義起來挺簡單的
```
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
```
2. 再比如,我的類上面新增一個 @Documented 註解,在生成文件的時候就會自動根據我寫的 doc去生成文件嗎?他是怎麼實現的?通過掃描註解類來完成嗎?
3. 再比如,之前用過的@bean 註解,我們在spring框架使用時候,在java類上定義之後,就會在載入的時候掃描載入到容器嗎?具體是怎麼實現的呢?
4. 我覺得我需要很明白的理解這寫問題。自己預估可能跟其他人提到的反射有關
#### 那麼。帶著這些個疑問,我們繼續向下學習。
---
### 註解與反射
上述內容我們介紹了註解使用上的細節,也簡單提到,「註解的本質就是一個繼承了 Annotation 介面的介面」,現在我們就來從虛擬機器的層面看看,註解的本質到底是什麼。
### 註解的使用例項
註解運用的地方太多了,如:
JUnit 這個是一個測試框架,典型使用方法如下:
```
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
```
還有例如ssm框架,springboot,springcloud等運用了大量的註解。
## 總結
算是對註解有了基本的認知。談談自我總結吧。
1. 如果註解難於理解,你就把它類同於標籤,標籤為了解釋事物,註解為了解釋程式碼。
2. 註解的基本語法,建立如同介面,但是多了個 @ 符號。
3. 註解的元註解。
4. 註解的屬性。
5. 註解主要給編譯器及工具型別的軟體用的。
6. 註解的提取需要藉助於 Java 的反射技術,反射比較慢,所以註解使用時也需要謹慎計較時間成本(需研究反射,!important)。
我之前的問題:
1. 我推論,我之前的問題,並不是出現在註解上面了。
2. 我之前的疑問的功能是通過註解,反射來完成的.註解只是起到了註解該完成的功能。
3. 接下來需要研究的是:反射。
通過反射機制會掃描出所有被@CodeQuery 修飾過的類或者介面並以bean物件的形式注入到自己的容器中來統一管理,根據被@CodeQuery修飾的介面或者類,就可以確定了被@CodeQuery修飾過得類都有哪些,遍歷所有Class檔案,然後可以用反射中的Method類來獲取所有被@SQL修飾過的方法的名字,通過方法名字就可以在程式執行時呼叫對應的介面來執行sql語句了
---
#### 參考文獻 :
- https://www.cnblogs.com/yangming1996/p/9295168.html
- https://www.cnblogs.com/love-menglong/p/11165469.html
- https://www.runoob.com/w3cnote/java-annotation.html
- https://blog.csdn.net/tainxiawuti/article/details/99644352
- https://www.cnblogs.com/skywang12345/ 《大佬》
#### 擴充套件作業
1. Class原始碼查閱並瞭解裡面的內建方法,如裡面提供的有檢視反射類的註解方法:
```
Class