女朋友說想要自己的注解,我又活下來了!!!
女朋友:我想要我自己的注解,你教我!
moon:誒?你怎么突然想要自己的注解了?
女朋友:關你什么事!「分手」!
moon:別別別別別!我教!
moon:看好了,我的寶~,你spring學的不錯,那我先帶你參觀下Autowired吧~
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
moon:看到 「Autowired」 發(fā)現(xiàn),這個類的「類名就叫 Autowired」,所以你知道為什么貼的是 @Autowired 了嗎?
女朋友:哦哦哦哦哦哦!我懂了!原來「類名就是注解名」!
moon:我女朋友就是聰明!我們再來看看,它還有一點比較特殊的地方,類的標志是 class,而「注解的標志是 @interface」。
女朋友:嗯.....不錯不錯,你繼續(xù)
moon:我們再來看下 @Autowired 上面還有三個注解,分別是什么作用,先來看第一個 「@Documented」
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
moon:看,我們發(fā)現(xiàn)了,第一個是 @Documented,我們來看看它的注釋是什么?

moon:通過我強大的英文閱讀能力,發(fā)現(xiàn) 「@Documented 注解其實只是用來生成文檔的」,使用 javadoc 就可以生成 api 文檔了,所以這個注解,肯定「不重要」
女朋友:呸!你明明是靠翻譯的!學渣!
moon:嘿嘿,我們再來看下一個!「@Retention」!這個可有的說頭了
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.2 @Retention
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
moon:再次通過我強大的英文閱讀能力看下,這個注釋到底是什么意思?

moon:其實它就是告訴你,該注解的「生命周期」有多久,而這個生命周期的定義,「就在 RetentionPolicy 里面」,我們再來看看這個 RetentionPolicy 到底是什么?
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.關注公眾號:moon聊技術,獲取更多有趣文章
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
女朋友:這個我熟!「SOURCE 的意思就是說被作用在源代碼上,CLASS 就是被作用在編譯出來的源碼上,RUNTIME 就是只作用在運行時」!這不就是 Java 的三種狀態(tài)嘛!
moon:你都學會搶答了我的寶!!!!
女朋友:哼!快繼續(xù)!!
moon:哈哈哈,好的,那我們就來說說最后一個注解 「@Target」
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
moon:這個注解的作用其實很簡單,「就是告訴你該注解可以被貼在哪些作用域中」,而作用域有哪些你知道嗎?
女朋友:嗯...有類、方法、成員變量.....
moon:哈哈哈哈哈,不知道了吧!!
女朋友:哼!!「分手」!!!!
moon:別別別別別別,聽我給你娓娓道來!這個作用域其實就藏在 「ElementType[]」 這個數(shù)組當中,我們進去看下!
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration 關注公眾號:moon聊技術,獲取更多有趣文章*/
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
moon:總共有「10種作用域」
| 作用域 | 含義 |
|---|---|
| TYPE | 用于描述類、接口(包括注解類型) 或enum聲明 |
| FIELD | 用于描述域 |
| METHOD | 用于方法 |
| PARAMETER | 用于描述參數(shù) |
| CONSTRUCTOR | 用于描述構造器 |
| LOCAL_VARIABLE | 用于描述局部變量 |
| ANNOTATION_TYPE | 用于描述注解 |
| PACKAGE | 用于描述包 |
| TYPE_PARAMETER | 表示該注解能使用在自定義類型參數(shù) |
| TYPE_USE | 是對類型的注解 |
所以當你確定你注解的作用域之后,你貼上 @Target(作用域),就可以了!
女朋友:噢噢噢噢,我懂了,那我有個問題,「如果我想讓我的子類也繼承這個注解該怎么做呢」?
moon:!!!!!!!這就是我接下來要講的!!「@Inherited」 !!也是 java 四大元注解之一(還有三個就是剛剛提到的@Target,@Retention,@Documented)!它的作用就是「讓子類也能繼承該父類的該注解」,那你知道該怎么用嘛?
女朋友:分....
moon:我來給你舉個例子!正好練習一下!
女朋友:哼!
moon:我們先寫個注解類
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
/**
* 說我愛你(默認true)
*/
boolean sayILoveYou() default true;
}
moon:這個注解很簡單,「只能作用在方法上,在運行時實現(xiàn),有個 syaILoveYou 的方法,默認是true!」
女朋友:yue~快說
moon:哈哈,再定義一個我,有個 sayLoveYou()方法,貼上了我們的 @MyAnnotation 注解,表達一下我的真心
public class Me {
@MyAnnotation
public void sayLoveYou(){
System.out.println("表達一下我的真心");
}
}
女朋友:yue~
moon:好了,現(xiàn)在我們開始測試了!
public class Main {
public static void main(String[] args) {
try {
//獲取Me的Class對象
Me me = new Me();
Class clazz = me.getClass();
//獲取該對象sayLoveYou方法上Info類型的注解
MyAnnotation myAnnotation = clazz.getMethod("sayLoveYou", null).getDeclaredAnnotation(MyAnnotation.class);
if (myAnnotation.sayILoveYou()) {
System.out.println("我愛你");
} else {
System.out.println("我不愛你");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
moon:我們先獲取到了 Me 的對象,然后獲取到了 MyAnnotation 這個注解,如果 myAnnotation.sayILoveYou() 為true,就會輸出"我愛你"!如果為false,就會輸出"我不愛你"!
女朋友:你不愛我,「我們分手」
moon:咳咳,測試測試~我們運行看下,結果一定是我愛你!因為我們默認為true

moon:我們修改下注解的默認值,結果就為我EN愛你了(滿滿的求生欲)
public class Me {
@MyAnnotation(sayILoveYou=false)
public void sayLoveYou(){
System.out.println("表達一下我的真心");
}
}

女朋友:哼~
moon:我們再試驗下 @Inherited 這個注解,修改下 MyAnnotation,「添加 @Inherited」,添「加 ElementType.TYPE 并且使其可以作用在類上」
@Retention(RetentionPolicy.RUNTIME)
@Target({Ele,mentType.METHOD,ElementType.TYPE})
@Inherited
public @interface MyAnnotation {
/**
* 說我愛你(默認true)
*/
boolean sayILoveYou() default true;
}
moon:Me 這個類在類上貼 @MyAnnotation 注解
@MyAnnotation
public class Me {
public void sayLoveYou(){
System.out.println("表達一下我的真心");
}
}
moon:然后我們假如有孩子了
public class Child extends Me{
}
女朋友:我不會和你結婚的!
moon:哈哈哈,假設假設,我們再來重寫 Main 方法
public static void main(String[] args) {
try {
//獲取child的Class對象
Child child = new Child();
Class clazz = child.getClass();
//獲取該對象sayLoveYou方法上Info類型的注解
MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
if (myAnnotation.sayILoveYou()) {
System.out.println("我愛你");
} else {
System.out.println("我不愛你");
}
} catch (Exception e) {
e.printStackTrace();
}
}
moon:「我們此時 child 對象是沒有 @MyAnnotation 注解的,只是繼承了我,但是由于我們再 Me 類貼了 @MyAnnotation 注解,并且有 @Inherited 注解,所以 child 也有該注解的功能,所以運行結果一定是我愛你!」

moon:這下你會了吧!注解就是這么簡單!
女朋友:哼,你還是有點用的,我不需要你了,你走吧
moon:好的老板!(終于教會了,我又活下來了)
一共分了多少次手,你們數(shù)清楚了嗎?
-- END --
-
| 更多精彩文章 -
▽加我微信,交個朋友 長按/掃碼添加↑↑↑



