JavaSE列舉類與註解 2021.07.07-10
阿新 • • 發佈:2021-07-12
JavaSE列舉類與註解 2021.07.07-10
勇敢牛牛,不怕困難!
列舉類
- 類的物件只有有限個,確定的,稱為列舉類。
- 當需要定義一組常量時,強烈建議使用列舉類
- 如果列舉類中只有一個物件,則可以作為單例模式的實現方式。
定義列舉類
方式一:jdk5.0 之前,自定義列舉類
方式二:jdk5.0 之後,可以使用enum關鍵字定義列舉類
自定義列舉類:
public class SeasonTest { public static void main(String[] args) { System.out.println(Season.SUMMER);//Season{seasonName='夏天', seasonDecs='夏日炎炎'} } } class Season{ //1.宣告Season的屬性:private final修飾 private final String seasonName; private final String seasonDecs; //2.私有化類的構造器,並給物件屬性賦值 private Season(String seasonName,String seasonDecs){ this.seasonName=seasonName; this.seasonDecs=seasonDecs; } //3.提供當前列舉類的多個物件:public static final public static final Season SPRING = new Season("春天","春暖花開"); public static final Season SUMMER = new Season("夏天","夏日炎炎"); public static final Season AUTUMN = new Season("秋天","秋高氣爽"); public static final Season WINTER = new Season("冬天","冰天雪地"); //4.其他訴求1:獲取列舉類物件的屬性 public String getSeasonName() { return seasonName; } public String getSeasonDecs() { return seasonDecs; } //5.其他訴求2:提供toString() @Override public String toString() { return "Season{" + "seasonName='" + seasonName + '\'' + ", seasonDecs='" + seasonDecs + '\'' + '}'; } }
使用enum關鍵字定義列舉類:
public class SeasonTest1 { public static void main(String[] args) { Season1 summer = Season1.SUMMER; System.out.println(summer);//SUMMER,因為父類Enum重寫了toString(),返回物件(常量)的名字 System.out.println(Season1.class.getSuperclass());//class java.lang.Enum,定義的列舉類預設繼承於java.lang.Enum類 } } enum Season1{ //1.提供當前列舉類的物件,多個物件之間用","隔開,末尾物件用";"結束 SPRING("春天","春暖花開"), SUMMER("夏天","夏日炎炎"), AUTUMN("秋天","秋高氣爽"), WINTER("冬天","冰天雪地"); //2.宣告Season1物件的屬性:private final修飾 private final String seasonName; private final String seasonDecs; //3.私有化類的構造器,並給物件屬性賦值 private Season1(String seasonName,String seasonDecs){ this.seasonName=seasonName; this.seasonDecs=seasonDecs; } //4.其他訴求1:獲取列舉類物件的屬性 public String getSeasonName() { return seasonName; } public String getSeasonDecs() { return seasonDecs; } }
Enum類的常用方法
- values():返回列舉型別的物件陣列。該方法可以很方便地遍歷所有的列舉值
- valueOf():可以把一個字串轉為對應的列舉類物件。要求字串必須是列舉類物件的“名字”。如不是,會有執行時異常:IllegalArgumentException
- toString():返回當前列舉類物件常量的名稱
//values(): Season1[] values = Season1.values(); for (int i = 0; i < values.length; i++) { System.out.println(values[i]); } /* SPRING SUMMER AUTUMN WINTER */ Thread.State[] values1 = Thread.State.values(); System.out.println(Arrays.toString(values1));//[NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED] //valueOf(String objName):返回列舉類中物件名是objName的物件 Season1 spring = Season1.valueOf("SPRING"); System.out.println(spring);//SPRING //Season1 spring1 = Season1.valueOf("SPRING1");//如果沒有objName對應的列舉類物件,則拋異常:IllegalArgumentException
使用關鍵字enum定義的列舉類實現介面
- 情況一:實現介面,在enum類中實現抽象方法
@Override
public void show() {
System.out.println("這是一個季節");
}
//main
Season1 spring = Season1.valueOf("SPRING");
System.out.println(spring);
spring.show();//這是一個季節
- 情況二:讓列舉類的物件分別實現介面中的抽象方法
SPRING("春天","春暖花開"){
@Override
public void show() {
System.out.println("春天來了");
}
},
SUMMER("夏天","夏日炎炎"){
@Override
public void show() {
System.out.println("夏天來了");
}
},
AUTUMN("秋天","秋高氣爽"){
@Override
public void show() {
System.out.println("秋天來了");
}
},
WINTER("冬天","冰天雪地"){
@Override
public void show() {
System.out.println("冬天來了");
}
};
//main
Season1[] values = Season1.values();
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]);
values[i].show();
}
/*
SPRING
春天來了
SUMMER
夏天來了
AUTUMN
秋天來了
WINTER
冬天來了
*/
註解(Annotation)
- jdk 5.0 新增的功能
- Annotation 其實就是程式碼裡的特殊標記,這些標記可以在編譯,類載入,執行時被讀取,並執行相應的處理。通過使用Annotation,程式設計師可以在不改變原有邏輯的情況下,在原始檔中嵌入一些補充資訊
- 在JavaSE中,註解的使用目的比較簡單,例如標記過時的功能,忽略警告等。在JavaEE/Android中註解佔據了更重要的角色,例如用來配置應用程式的任何切面,代替JavaEE舊版中所遺留的繁冗程式碼和XML配置等。
- 一定程度上,框架 = 註解 + 反射 + 設計模式
示例
一、生成文件相關的註解
-
@author 標明開發該類模組的作者,多個作者之間使用","分隔
-
@version 標明該類模組的版本
-
@see 參考轉向,也就是相關主題
-
@since 從哪個版本開始增加的
-
@param 對方法中某引數的說明,如果沒有引數就不能寫
-
@return 對方法返回值的說明,如果方法的返回值型別是void就不能寫
-
@exception 對方法可能丟擲的異常進行說明,如果方法沒有用throws顯式丟擲的異常就不能寫
-
其中
- @param @return @exception 這三個標記都是隻用於方法的
- @param 的格式要求:@param 形參名 形參型別 形參說明
- @return 的格式要求 :@return 返回值型別 返回值說明
- @exception 的格式要求:@exception 異常型別 異常說明
- @param 和@exception可以並列多個
二、在編譯時進行格式檢查(JDK內建的三個基本註解)
- @Override:限定重寫父類方法,該註解只能用於方法(在編譯時進行校驗,只能是重寫父類的方法)
- @Deprecated:用於表示所修飾的元素(類,方法等)已過時。通常是因為所修飾的結構危險或存在更好的選擇
- @SuppressWarnings:抑制編譯器警告 (如@SuppressWarnings({"unused","rawtypes"}), @SuppressWarnings("unused"))
三、跟蹤程式碼依賴性,實現替代配置檔案功能
自定義註解
參照@SuppressWarnings定義
- 註解宣告為@interface
- 內部定義成員,通常使用value()表示
- 可以指定成員的預設值,使用default定義
- 如果自定義註解沒有成員,表明是一個標識作用
- 如果註解有成員,在使用註解時,需要指明成員的值。
- 自定義註解必須配上註解的資訊處理流程(使用反射)才有意義。
- 自定義註解通常都會指明兩個元註解:Retention、Target
public @interface MyAnnotation {
String value() /*default "hello" 指定預設值*/ ;
}
//使用
@MyAnnotation(/*value =*/ "hello")
自定義註解自動繼承java.lang.annotation.Annotation介面
Annotation的成員變數在定義中以無參方法的形式來宣告。其方法名和返回值定義了該成員的名字和型別,稱為配置引數。型別只能是八種基本型別、String型別、Class型別、enum型別、Annotation型別、以上所有型別的陣列。
jdk提供的4種元註解
元資料:對現有的資料進行解釋說明的資料
比如 String name = "beckham";beckham是資料的話,String name 就是元資料
元註解:對現有的註解進行解釋說明的註解
@Retention
指定所修飾的Annotation的生命週期:
包含一個RetetionPolicy型別(列舉類)的成員變數,使用時必須為該value成員變數指定值:
- RetentionPolicy.SOURCE:在原始檔中有效(原始檔保留,java檔案)編譯器直接丟棄這種註釋。
- RetentionPolicy.CLASS:在class檔案中有效(class保留,java檔案經過編譯後得到class檔案,即javac.exe命令(編譯)),當執行Java程式時,JVM不會保留註釋。這是預設值。
- Retention.RUNTIME:在執行時有效(執行時保留),當執行Java程式時,JVM會保留註釋。只有宣告為RUNTIME生命週期的註解,才能通過反射獲取。
@Target
用於指定被修飾的 Annotation 能用於修飾哪些程式元素
包含一個名為ElementType(列舉類)的成員變數
@Documented(使用頻率低)
- 表示所修飾的註解在被 javadoc 解析時,保留下來。預設情況下,javadoc不保留註解。
- 定義為Documented的註解必須設定Retention值為RUNTIME
@Inherited(使用頻率低)
- 被修飾的Annotation具有繼承性
通過反射獲取註解資訊(暫時瞭解一下)
//驗證Inherited 的繼承性
//main
Class studentClass = Student.class;
Annotation[] annotations = studentClass.getAnnotations();
for (int i = 0; i < annotations.length; i++) {
System.out.println(annotations[i]);//@com.annotationTest.MyAnnotation(value=hello)
}
@MyAnnotation(/*value =*/ "hello")
class Person{
}
class Student extends Person{
}
jdk 8.0 中註解的新特性
可重複註解
jdk 8之前的寫法:
//
public @interface MyAnnotation {
String value() /*default "hello"*/ ;
}
public @interface MyAnnotations {
MyAnnotation[] value();
}
//使用重複註解,新建註解MyAnnotations,定義MyAnnotation陣列
@MyAnnotations({@MyAnnotation(value = "hello"),@MyAnnotation(value = "hi")})
jdk 8 之後的寫法:
- 在MyAnnotation上宣告@Repeatable,成員值為MyAnnotations.class
- MyAnnotation的Target和Retention等元註解 與 MyAnnotations的相同
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
public @interface MyAnnotation {
String value() /*default "hello"*/ ;
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
public @interface MyAnnotations {
MyAnnotation[] value();
}
//使用重複註解
@MyAnnotation(value = "hello")
@MyAnnotation(value = "hi")
型別註解
- jdk 8之後,元註解@Target的引數型別ElementType列舉值多了兩個:TYPE_PARAMETER,TYPE_USE
- jdk 8開始,註解可以應用在任何地方。
- ElementType.TYPE_PARAMETER 表示該註解能寫在型別變數的宣告語句中(如:泛型宣告)
- ElementType.TYPE_USE 表示該註解能寫在使用型別的任何語句中。
class Teacher <@MyAnnotation T>{ //ElementType.TYPE_PARAMETER,ElementType.TYPE_USE 都可以修飾
public void show() throws @MyAnnotation RuntimeException{ //ElementType.TYPE_USE
ArrayList<@MyAnnotation String> list = new ArrayList(); //ElementType.TYPE_USE
int num = (@MyAnnotation int)10L; //ElementType.TYPE_USE
}
}
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
public @interface MyAnnotation {
String value() default "hello" ;
}