CF1238E.Keyboard Purchase 題解 狀壓/子集劃分DP
阿新 • • 發佈:2020-09-03
3 註解
3.1 註解,或者叫做註釋型別,英文單詞是:Annotation
疑問:註解是幹什麼的?
3.2 註解Annotation是一種引用資料型別。編譯之後也是生成xxx.class檔案。
3.3 怎麼自定義註解呢?語法格式?
[修飾符列表]@interface 註解型別名{
}
3.4 註解怎麼使用,用在什麼地方?
第一:註解使用時的語法格式是:
@註解型別名
第二:註解可以出現在類上、屬性上、方法上、變數上等。。。
註解還可以出現在註解型別上。
3.5 JDK內建了哪些註解?
掌握:
Deprecated 用 @Deprecated 註釋的程式元素,不鼓勵程式設計師使用這樣的元素,通常是因為它很危險或存在更好的選擇。
掌握:
Override 表示一個方法宣告打算重寫超類中的另一個方法宣告。
瞭解:
SuppressWarnings 指示應該在註釋元素(以及包含在該註釋元素中的所有程式元素)中取消顯示指定的編譯器警告。
3.6 元註解
什麼是元註解?
用來標註“註解型別”的“註解”,稱為元註解。
常見的元註解有哪些呢?
Target
Retention
關於Target註解:
這是一個元註解,用來標註“註解型別”的“註解”
這個Target註解用來標註“被標註的註解”可以出現在哪些位置上。
@Target(ElementType.METHOD):表示“被標註的註解”只能出現在方法上。
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
表示該註解可以出現在:
構造方法上
欄位上
區域性變數上
方法上
...
類上...
3.7 Retention的原始碼:
// 元註解
public @interface Retention {
// 屬性
}
RetentionPolicy的原始碼:
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
3.8 Target的原始碼
關於Retention註解:
這是一個元註解,用來標註“註解型別”的“註解”
這個Retention註解用來標註“被標註的註解”最終儲存在哪裡。
@Retention(RetentionPolicy.SOURCE):表示該註解紙杯保留在java原始檔中。
@Retention(RetentionPolicy.Class):表示該註解被儲存在class檔案中。
@Retention(RetentionPolicy.RUNTIME):表示該註解被儲存在class檔案中,並且可以被反射機制所讀取。
3.9 註解在開發中有什麼用呢?
需求:
假設有這樣一個註解,叫做:@Id
這個註解只能出現在類上面,當這個類上有這個註解的時候,要求這個類中必須有一個int型別的id屬性。
如果沒有這個屬性就報異常。如果有這個屬性則正常執行!
案例1:
package com.javaSe.annotation; /* 1 註解,或者叫做註釋,英文單詞是:Annotation 2 註解Annotation是一種引用資料型別。編譯之後也是生成xxx.class檔案。 3 怎麼自定義註解呢?語法格式? [修飾符列表]@interface 註解型別名{ } 4 預設情況下,註解可以出現在任意位置。 */ @MyAnnotation public class AnnotationTest01 { @MyAnnotation private int no; @MyAnnotation public static void m1(){ @MyAnnotation int i = 100; } @MyAnnotation public static void m2(@MyAnnotation String name, @MyAnnotation int k){ } @MyAnnotation public AnnotationTest01() { } @MyAnnotation public AnnotationTest01(int no) { this.no = no; } } @MyAnnotation interface MyInterface{ } @MyAnnotation enum Season{ SPRING,SUMMER,AUTUMN,WINTER }關於JDK當中的override(編譯)註解:
package com.javaSe.annotation; /* 關於JDK lang包下的override註解 原始碼: public @interface Override {} @Override這個註解只能註解方法。 @Override這個註解是給編譯器參考的,和執行階段沒有關係。 @Override凡是java中的方法帶有這個註解的,編譯器都會進行編譯檢查,如果這個方法不是重寫父類的方法,編譯器報錯。 標識性註解,給編譯器作參考的。 編譯器看到方法上有這個註解的時候,編譯器會自動檢查該方法是否重寫了父類的方法。 如果沒有重寫,報錯。 這個只是在編譯階段起作用,和執行期無關。 */ public class AnnotationTest02 { @Override public String toString() { return "toString()"; } public static void main(String[] args) { } }
關於JDK當中的Deprecated(已過時)註解:
package com.javaSe.annotation; // 表示這個類已過時。 // @Deprecated public class AnnotationTest03 { public static void main(String[] args) { AnnotationTest03 at = new AnnotationTest03(); at.doSome(); } @Deprecated public void doSome(){ System.out.println("do something!"); } // Deprecated這個註解標註的元素已過時。 // 這個註解主要是向其他程式設計師傳達一個資訊,告知已過時,有更好的解決方案存在。 @Deprecated public static void doOther(){ System.out.println("do other..."); } } class T{ public static void main(String[] args) { AnnotationTest03 at = new AnnotationTest03(); at.doSome(); AnnotationTest03.doOther(); } }
自定義註解:
package com.javaSe.annotation; /* 自定義註解:MyAnnotation */ public @interface MyAnnotation { }
註解修飾註解:
package com.javaSe.annotation; // 註解修飾註解 @MyAnnotation public @interface OtherAnnotation { }
自定義註解:
package com.javaSe.annotation2; public @interface MyAnnotation { /** * 我們通常在註解當中可以定義屬性,以下是MyAnnotation的name屬性。 * 看著像一個方法,但實際上我們稱之為屬性name。 * @return */ String name(); /** * 顏色屬性 * @return */ String color(); /** * 年齡屬性 * @return */ int age() default 25; // 屬性指定預設值 }
註解中的屬性用法:
package com.javaSe.annotation2; public class MyAnnotationTest { // 報錯的原因:如果一個註解當中有屬性,那麼必須給屬性賦值。(除非該屬性使用了default指定了預設值) /*@MyAnnotation() public void doSome(){ }*/ // @MyAnnotation(屬性名=屬性值) // 指定name的屬性值就好了 @MyAnnotation(name="zhangsan",color = "紅色") public void doSome(){ } }
自定義註解:
package com.javaSe.annotation3; public @interface MyAnnotation { /** * 指定一個value屬性 * @return */ String value(); // String email(); }
如果註解中的屬性是value,而且只有一個屬性的時候,value可以省略:
package com.javaSe.annotation3; /* 如果一個註解的屬性的名字是value的話,並且只有一個屬性的話,在使用的時候,該屬性名可以省略。 */ public class MyAnnotationTest { // 報錯原因:沒有指定屬性的值。 /*@MyAnnotation() public void doSome(){ }*/ @MyAnnotation(value = "hehe") public void doSome(){ } @MyAnnotation("haha") public void doOther(){ } }
自定義註解:
package com.javaSe.annotation3; public @interface OtherAnnotation { String name(); }
如果註解中的屬性不是value,那麼會報錯
package com.javaSe.annotation3; public class OtherAnnotationTest { // 報錯了,因為屬性名是name,不能省略。 // @OtherAnnotation("test") // 正確的 @OtherAnnotation(name = "test") public void doSome(){ } }自定義註解(註解當中的屬性可以是哪一種型別?):
package com.javaSe.annotation4; public @interface MyAnnotation { /* 註解當中的屬性可以是哪一種型別? byte short int long float double double char String Class 列舉型別 以及以上每一種陣列形式 */ int value1(); String value2(); int[] value3(); String[] value4(); Season value5(); Season[] vakye6(); Class parameterType(); Class[] parameterTypes(); }
自定義列舉:
package com.javaSe.annotation4; public enum Season { SPRING,SUMMER,ANTUMN,WINTER }
自定義註解:
package com.javaSe.annotation4; public @interface OtherAnnotation { /** * 年齡屬性 * @return */ int age(); /** * 郵箱陣列,支援多個 * @return */ String[] email(); /** * 季節陣列,Season是列舉型別 * @return */ Season[] seasonArray(); }
如果註解是陣列的話,該如何使用:
package com.javaSe.annotation4; import java.lang.annotation.Retention; public class OtherAnnotationTest { // 陣列是大括號 @OtherAnnotation(age = 25, email = {"123","234","345","456"},seasonArray = Season.WINTER) public void doSome(){ } @Deprecated // 如果陣列中只有一個元素:大括號可以省略 @OtherAnnotation(age = 25, email = "789",seasonArray = {Season.SPRING,Season.SUMMER}) public void doOther(){ } }
自定義註解:
package com.javaSe.annotation5; 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 MyAnnotation { String value() default "黑龍江"; }
使用註解:
package com.javaSe.annotation5; /* 為什麼註解不能用在成員變數和區域性變數中還有構造方法中,因為你沒有在註解類中定義。 */ @MyAnnotation("四川雅安") public class MyAnnotationTest { // @MyAnnotation int i; @MyAnnotation public void doSome(){ // @MyAnnotation int i; } // @MyAnnotation public MyAnnotationTest() { } }
通過反射機制獲取註解:
package com.javaSe.annotation5; public class ReflectAnnotationTest { public static void main(String[] args) throws Exception{ // 獲取這個類 Class c = Class.forName("com.javaSe.annotation5.MyAnnotationTest"); // 判斷類上面是否有這個註解 boolean b = c.isAnnotationPresent(MyAnnotation.class); // System.out.println(b);// true if(b){ // 獲取該註解物件 MyAnnotation mt = (MyAnnotation) c.getAnnotation(MyAnnotation.class); // System.out.println("類上面的註解物件" + mt); //類上面的註解物件@com.javaSe.annotation5.MyAnnotation() // 獲取註解物件的屬性怎麼辦?和調介面沒區別。 String value = mt.value(); System.out.println(value); } // 判斷String類上面是否存在這個註解 Class stringClass = Class.forName("java.lang.String"); boolean b1 = stringClass.isAnnotationPresent(String.class); System.out.println(b1);// false } }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
註解在程式中的用處:程式碼如下:
自定義@Id註解
package com.javaSe.annotation7; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 表示這個註解只能出現在類上面 @Target(ElementType.TYPE) // 表示該註解可以被反射機制讀取到 @Retention(RetentionPolicy.RUNTIME) public @interface Id { } // 這個註解@Id用來標註類,被標註的類中必須有一個int型別的id屬性,沒有就報異常
User使用者業務類:
package com.javaSe.annotation7; @Id public class User { int id; String name; String password; }
測試程式:
package com.javaSe.annotation7; import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception{ // 獲取類 Class userClass = Class.forName("com.javaSe.annotation7.User"); // 判斷類上是否存在@Id註解 if(userClass.isAnnotationPresent(Id.class)){ // 當一個類上有@Id註解的時候,要求類中必須存在int型別的id屬性 // 如果沒有int型別的id屬性則報異常。 // 獲取類的屬性 Field[] fields = userClass.getDeclaredFields(); boolean isOk = false;// 給一個預設的標記 for (Field field : fields){ if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){ // 表示這個類是合法的類。有@Id註解,則這個類中必須有int型別的id isOk = true; // 表示合法 break; } } // 判斷是否合法 if(!isOk){ throw new HasNotIdPropertyException("被@Id註解標註的類中必須要有一個int型別的id屬性!"); } } } }
自定義異常:
package com.javaSe.annotation7; /* 自定義異常 */ public class HasNotIdPropertyException extends RuntimeException{ public HasNotIdPropertyException(){ } public HasNotIdPropertyException(String s){ super(s); } }