第十九天 註釋
阿新 • • 發佈:2021-02-01
定義
- 註解,亦叫做註釋,英文單詞:Annotation
- 註解Annotation是一種引用資料型別,編譯之後也是生成xxx.class檔案
- 怎麼樣自定義註解?語法格式是啥?
[ 修飾符列表 ] @interface 註解型別名{ }
- 使用註解的語法格式:
@註解型別名
- 註解用在什麼地方法
- 註解可以用在類上、屬性上、方法上、變數上…
- 註解甚至能出現在註解型別上
註解類
public @interface MyAnnotation {
}
註解使用的位置
package Day19註解;
public class Test01 {
@MyAnnotation //屬性
private int no;
@MyAnnotation //構造方法
public Test01() {}
@MyAnnotation //靜態方法
public static void doSome(){}
@MyAnnotation //例項方法
public void doOther(){
@MyAnnotation //區域性變數
int i = 1;
}
public void m1(@MyAnnotation String name) {} //形參
}
@MyAnnotation //介面
interface MyInterface{}
@MyAnnotation //列舉
enum Season{
SPRING,SUNMER,AUTUMN,WINTER
}
和
package Day19註解;
@MyAnnotation //其他註釋
public @interface OtherAnnotation {
}
綜上所述:註釋能出現在:屬性、構造方法、靜態方法、例項方法、區域性變數、介面、列舉型別、其他註釋上
Override註解
註解型別 | 描述 |
---|---|
Deprecated | 一個程式單元註釋”不是一個程式設計師應該使用,通常是因為它是危險的,因為一個更好的選擇的存在。 |
Override | 表示一個方法宣告的目的是覆蓋父類方法宣告。 |
SuppressWarnings | 指示在註釋元素(和包含在註釋元素中的所有程式元素中)應被抑制命名的編譯器警告。 |
Override註解
package Day19註解;
public class Test02 {
/*
Override的原始碼:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}
* */
@Override
public String toString() {
return "toString";
}
}
解釋:
@Override這個註解只能註解方法
該註解是給編譯器參考的,和執行階段沒有關係,如果java中的方法帶有這個註解,編譯器就會進行編譯檢查,如果該方法沒有重寫父類的方法,則報錯
元註解
- 定義:標註“註解型別”的註解
- 常見的元註解
- Target
- Retention
- Target
- 這是一個元註解,用來標註“註解型別”的註解
- 作用:限制被標註的註解出現的位置
- 例項
@Target(ElementType.METHOD)
//表示被該註解標註的註解只能出現在方法上
- Retention
- 標註“被標註的註解”最終儲存在哪裡
- 例項
@Retention(RetentionPolicy.SOURCE)
//表示該註解只是被保留在Java原始檔中
@Retention(RetentionPolicy.CLASS)
//表示該註解被儲存在class檔案中
@Retention(RetentionPolicy.RUNTIME)
//表示該註解被儲存在class檔案中,並且可以被反射機制所讀取
Deprecated註解
作用:告訴其他人這個東西已經過時了,目前已經有了更好的解決方案
package Day19註解;
@Deprecated
public class Test03 {
public static void main(String[] args) {
Test03 test03 = new Test03();
test03.doSome();
}
@Deprecated
public static void doSome(){
System.out.println("do Something...");
}
public static void doOther(){
System.out.println("do Other thing...");
}
}
class Test04{
public static void main(String[] args) {
Test03 test03 = new Test03();
test03.doOther();
try {
Class<?> aClass = Class.forName("Day19註解.Test03");
Object object = aClass.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-wC73NyzH-1612032291499)(en-resource://database/708:1)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-s2ZWQoiH-1612032291501)(en-resource://database/710:1)]
表示該方法和該類均被淘汰了
註解定義屬性
自定義屬性
package Day19註解;
public @interface MyAnnotation {
String name();
String color();
int age = 21; //屬性指定預設值
}
測試
package Day19註解;
public class Test05 {
// @YourAnnotation()
// public void doSome(){}
// 對於元素name,color, 註釋 @Day19註解.YourAnnotation 缺少預設值
@YourAnnotation(name = "張三", color = "black")
public void doSome(){}
public static void main(String[] args) {}
}
注意事項:
- 在註解中也是可以定義屬性的
- 雖然屬性後面有個小括號,看著很像是方法,但是這實際上就是註釋的屬性
- 如果註解中有屬性,則必須給屬性賦值,除非本身就使用default指定了預設值
屬性是value的時候
當註解僅有一個value屬性的時候:
註解類:
package Day19註解;
public @interface YourAnnotation2 {
String value();
}
測試:
package Day19註解;
public class Test06 {
@YourAnnotation2(value = "張三")
public void doSome(){}
@YourAnnotation2("李四")
public void doOther(){}
public static void main(String[] args) {}
}
注意事項:
當註釋中僅有一個屬性,且該屬性的名字是value的時候,在呼叫該註釋的時候,小括號中的“value = ”可以直接省略
當註釋不僅僅有一個value屬性的時候
註解類:
package Day19註解;
public @interface YourAnnotation3 {
String value();
String name();
}
測試:
package Day19註解;
public class Test07 {
@YourAnnotation3(value = "李四", name = "張三")
public void doSome(){}
public static void main(String[] args) {}
}
注意事項:
當先將“value = ”省略的時候,去填name,IDEA會自動的將“value = ”加上,如果沒有,則會報錯
屬性是一個數組
- 註解的屬性型別可以是:byte short int long float double boolean char String Class 列舉型別
package Day19註解;
public @interface MyAnnotation2 {
int value1();
String value2();
int[] value3();
String value4();
Season value5();
Season[] value6();
Class parameterType();
Class[] parameterTypes();
}
列舉:
package Day19註解;
public enum Season2 {
SPRING,SUMMER,AUTUMN,WINTER
}
屬性為列舉型別:
package Day19註解;
public @interface MyAnnotation3 {
int age();
String[] name();
Season[] seasonArray();
}
測試:
package Day19註解;
public class Test08 {
@MyAnnotation3(age = 21, name = {"張三", "李四"}, seasonArray = {Season.AUTUMN,Season.SPRING})
public void doSome(){}
@MyAnnotation3(age = 21, name = "張三", seasonArray = {Season.AUTUMN,Season.SPRING})
public void doOther(){}
}
注意事項:
- 列舉型別的屬性寫入的時候,需要加列舉型別的名字
- 如果陣列只有1個元素,大括號是可以省略的
反射註解
自定義註解:
package Day19註解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//該註解只能標記類和方法
@Target({ElementType.TYPE,ElementType.METHOD})
//該註解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation4 {
String value() default "廣東廣州";
}
測試註解:
package Day19註解;
@MyAnnotation4("四川成都")
public class Test09 {
// @MyAnnotation4("四川成都") //因為Target標註限制,所以MA4註釋不能註釋屬性
int i;
// @MyAnnotation4("四川成都") //因為Target標註限制,所以MA4註釋不能註釋構造方法
public Test09(){}
@MyAnnotation4("四川成都")
public void doSome(){
// @MyAnnotation4("四川成都") //因為Target標註限制,所以MA4註釋不能註釋區域性變數
int i;
System.out.println("doSome...");
}
}
通過反射獲取類的註釋
package Day19註解;
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException {
//獲取類
Class<?> t9Class = Class.forName("Day19註解.Test09");
//判斷該類上是否存在MyAnnotation4註釋
if (t9Class.isAnnotationPresent(MyAnnotation4.class)){
//獲取該註釋物件
MyAnnotation4 t9ClassAnnotation = t9Class.getAnnotation(MyAnnotation4.class);
//輸出該註釋物件
System.out.println(t9ClassAnnotation);
//獲取註釋物件的屬性值
String value = t9ClassAnnotation.value();
//輸出屬性
System.out.println(value);
}
//對比實驗,判斷String類上面有無@MyAnnotation4
//獲取類
Class<?> aClass = Class.forName("java.lang.String");
if (aClass.isAnnotationPresent(MyAnnotation4.class)){
System.out.println(aClass.getAnnotation(MyAnnotation4.class));
} else {
System.out.println(aClass.getSimpleName() + "型別不存在MyAnnotation4註釋");
}
}
}
注意事項:
- 是判斷某個java檔案是否存在某種型別的註釋,所以獲取的是該java檔案的類,而不是該註釋的類
- 獲取到後就需要進行判斷是否存在該註釋,使用isAnnotationPresent()方法
通過反射獲取註解物件的值
自定義註解:
package Day19註解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation5 {
String name();
String id();
}
測試:
package Day19註解;
//獲取本類doSome()方法上面的註釋資訊
import java.lang.reflect.Method;
public class Test11 {
@MyAnnotation5(name = "張三", id = "001")
public void doSome(){}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//獲取本類
Class<?> t11Class = Class.forName("Day19註解.Test11");
//獲取doSome()方法
Method dsMethod = t11Class.getMethod("doSome");
//判斷doSome()方法是否存在註解
if (dsMethod.isAnnotationPresent(MyAnnotation5.class)){
//獲取該註釋物件
MyAnnotation5 dsMethodAnnotation = dsMethod.getAnnotation(MyAnnotation5.class);
System.out.println("使用者的名字是:" + dsMethodAnnotation.name() + ",id是:" + dsMethodAnnotation.id());
} else {
System.out.println(t11Class.getSimpleName() + "的" + dsMethod.getName() + "沒有MyAnnotation5的註釋");
}
//對比試驗,判斷Test09類中的doSome()方法有無@MyAnnotation5註釋
Class<?> aClass = Class.forName("Day19註解.Test09");
Method doSome = aClass.getMethod("doSome");
if (doSome.isAnnotationPresent(MyAnnotation5.class)){
MyAnnotation5 annotation = doSome.getAnnotation(MyAnnotation5.class);
System.out.println("使用者的名字是:" + annotation.name() + ",id是:" + annotation.id());
} else {
System.out.println(aClass.getSimpleName() + "的" + doSome.getName() + "沒有MyAnnotation5的註釋");
}
}
}