列舉和注釋
筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)
自定義類實作列舉
先看一個需求
要求創建季節(Season)物件,請設計并完成,
創建Season物件有如下特點
1.季節的值是有限的幾個值(spring, summer, autumn, winter)
2.只讀,不需要修改,
public class Test {
public static void main(String[] args) {
//使用
Season spring = new Season("春天", "溫暖");
Season winter = new Season("冬天","寒冷");
Season summer = new Season("夏天","炎熱");
Season autumn = new Season("秋天","涼爽");
//autumn.setName("XXX");
//autumn.setDesc("非常的熱..");
//因為對于季節而已,他的物件(具體值),是固定的四個,不會有更多
//按照這個設計類的思路,不能體現季節是固定的四個物件
//因此,這樣的設計不好===>列舉類[枚:一個一個舉:例舉,即把具體的物件一個一個例舉出來的類
//就稱為列舉類]
Season other = new Season("紅天","~~" );
}
}
class Season {
private String name;
private String desc;//描述
public Season(String name, String desc) {this.name = name;this.desc = desc;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String getDesc() { return desc;}
public void setDesc(String desc) {this.desc = desc;}
}
解決方案-列舉
- 列舉對應英文(enumeration,簡寫enum)
- 列舉是一組常量的集合,
- 可以這里理解:列舉屬于一種特殊的類,里面只包含一組有限的特定的物件,
列舉的二種實作方式
- 自定義類實作列舉
- 使用enum關鍵字實作列舉
package enum_;
public class Test {
public static void main(String[] args) {
System.out.println(Season.AUTUMN);
System.out.println(Season.SPRING);
}
}
//演示定義列舉實作
class Season {
private String name;
private String desc;//描述
//定義了四個物件,固定.
public static final Season SPRING = new Season("春天","溫暖");
public static final Season WINTER = new Season("冬天","寒冷");
public static final Season AUTUMN = new Season("秋天","涼爽");
public static final Season SUIMMER = new Season("夏天","炎熱");
//1.將構造器私有化,目的防止直接new
//2.去掉setXxx方法,防止屬性被修改
//3.在Season內部,直接創建固定的物件
//4.優化,可以加入final修飾符
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
小結:進行自定義類實作列舉,有如下特點;
-
構造器私有化
-
本類內部創建一組物件
-
對外暴露物件(通過為物件添加public final static修飾符)
-
可以提供get方法,但是不要提供set
enum關鍵字實作列舉
使用enum來實作前面的列舉案例,看演示,主要體會和自定義類實作列舉不同的地方,
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING);
}
}
//演示定義列舉實作
enum Season {
//定義了四個物件,固定.
// public static final Season SPRING = new Season("春天","溫暖");
// public static final Season WINTER = new Season("冬天","寒冷");
// public static final Season AUTUMN = new Season("秋天","涼爽");
// public static final Season SUIMMER = new Season("夏天","炎熱");
//如果使用了enum來實作列舉類//1,使用關鍵字 enum替代 class
//2. public static final Season SPRING = new Season("春天","溫暖")直接使用//SPRING("春天","溫暖"))解讀常量名(實參串列I
//3.如果有多個常量(物件),使用,號間隔即可
//4.如果使用enum 來實作列舉,要求將定義常量物件,寫在前面
SPRING("春天", "溫暖"), WINTER("冬天", "寒冷");;
private String name;
private String desc;//描述
//1.將構造器私有化,目的防止直接new
//2.去掉setXxx方法,防止屬性被修改
//3.在Season內部,直接創建固定的物件
//4.優化,可以加入final修飾符
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
enum關鍵字實作列舉注意事項
-
當我們使用enum 關鍵字開發一個列舉類時,默認會繼承Enum類[如何證明:用javap指令反編譯能看見繼承自Enum]

-
傳統的public static final Season2 SPRING = new Season2("春天""溫暖");簡化成SPRING(“春天","溫暖"),這里必須知道,它呼叫的是哪個構造器.
-
如果使用無參構造器創建列舉物件,則實參串列和小括號都可以省略
enum Season { SPRING("春天", "溫暖"),AUTUMN;; private Season() { } //...... } -
當有多個列舉物件時,使用,間隔,最后有一個分號結尾
-
列舉物件必須放在列舉類的行首.
舉例說明enum常用的方法的使用
-
toString:Enum類已經重寫過了,回傳的是當前物件名,子類可以重寫該方法,用于回傳物件的屬性資訊
-
name:回傳當前物件名(常量名),子類中不能重寫
-
ordinal:回傳當前物件的位置號,默認從0開始
-
values:回傳當前列舉類中所有的常量(此處常量即列舉物件)(value方法被隱藏了,原始碼中找不到)
-
valueOf:將字串轉換成列舉物件,要求字符串必須為已有的常量名,否則報例外!
-
compareTo: 比較兩個列舉常量,比較的就是編號!
public class Test {
public static void main(String[] args) {
//使用Season2列舉類,來演示各種方法
Season2 autumn = Season2.AUTUMN;
//輸出列舉物件的名字
System.out.println(autumn.name());
//ordinal()輸出的是該列舉物件的次序/編號,從0開始編號
// AUTUMN列舉物件是第三個,因此輸出2
System.out.println(autumn.ordinal());
//從反編譯可以看出values方法,回傳Season2[]
//含有定義的所有列舉物件
Season2[] values = Season2.values();
System.out.println("===遍歷取出列舉物件(增強for)====");
for (Season2 season : values) {//增強for回圈
System.out.println(season);
}
//valueOf:將字串轉換成列舉物件,要求字串必須VT為已有的常量名,否則報例外
// 執行流程
// 1.根坍你輸入的“AUTUMN ”到Season2的列舉物件去查找
// 2.如果找到了,就回傳,.如果沒有找到,就報錯
Season2 autumn1 = Season2.valueOf("AUTUMN");
System.out.println("autumn1=" + autumn1);
System.out.println(autumn == autumn1);
//compareTo:比較兩個列舉常量,比較的就是編號
//2.看看結果
/*
public final int compareTo(E o) {
return self.ordinal - other.ordinal;
}
Season2.AUTUMN的編號[3] - Season2.SUMMER的編號[1]
*/
System.out.println(Season2.AUTUMN.compareTo(Season2.SUMMER));//3-1
}
}
//演示定義列舉實作
enum Season2 {
//定義了四個物件,固定.
// public static final Season SPRING = new Season("春天","溫暖");
// public static final Season WINTER = new Season("冬天","寒冷");
// public static final Season AUTUMN = new Season("秋天","涼爽");
// public static final Season SUMMER = new Season("夏天","炎熱");
//如果使用了enum來實作列舉類//1,使用關鍵字 enum替代 class
//2. public static final Season SPRING = new Season("春天","溫暖")直接使用//SPRING("春天","溫暖"))解讀常量名(實參串列I
//3.如果有多個常量(物件),使用,號間隔即可
//4.如果使用enum 來實作列舉,要求將定義常量物件,寫在前面
SPRING("春天", "溫暖"),
SUMMER("夏天", "炎熱"),
WINTER("冬天", "寒冷"),
AUTUMN;
Season2() {
}
private String name;
private String desc;//描述
//1.將構造器私有化,目的防止直接new
//2.去掉setXxx方法,防止屬性被修改
//3.在Season內部,直接創建固定的物件
//4.優化,可以加入final修飾符
private Season2(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {return name;}
public String getDesc() { return desc;}
}
注意
-
使用enum關鍵字后,就不能再繼承其它類了,因為enum會隱式繼承Enum,而Java是單繼承機制,
-
列舉類和普通類一樣,可以實作介面,如下形式,
enum 類名 implements 介面1,介面2{}
JDK內置的基本注解型別(了解就行)
注解的理解
- 注解(Annotation)也被稱為元資料(Metadata),用于修飾解釋包、類、方法、屬性、構造器、區域變數等資料資訊,
- 和注釋一樣,注解不影響程式邏輯,但注解可以被編譯或運行,相當于嵌入在代碼中的補充資訊,
- 在JavaSE中,注解的使用目的比較簡單,例如標記過時的功能,忽略警告等,在JavaEE中注解占據了更重要的角色,例如用來配置應用程式的任何切面,代替java EE舊版中所遺留的繁冗代碼和XML配置等,
基本的Annotation介紹
使用Annotation時要在其前面增加@符號,并把該Annotation當成一個修飾符使用,用于修飾它支持的程式元素
三個基本的Annotation:
- @Override:限定某個方法,是重寫父類方法,該注解只能用于方法
- @Deprecated:用于表示某個程式元素(類,方法等)已過時
- @SuppressWarnings:抑制編譯器警告
@Override
Override:限定某個方法,是重寫父類方法,該注解只能用于方法
class Father{
public void fly(){
System.out.println("Father fly.….");
}
}
class Son extends Father {
//解讀
//1.@Override 注解放在fly方法上,表示子類的fly方法時重寫了父類的fly
//2.這里如果沒有寫@0verride還是重寫了父類fly
//3.如果你寫了@Override注解,編譯器就會去檢查該方法是否真的重寫了父類的
// 方法,如果的確重寫了,則編譯通過,如果沒有構成重寫,則編譯錯誤
/*
@Target(ElementType.HETHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
*/
@Override //說明
public void fly() {
System.out.println("Son fly...");
}
}
> 補充說明:@interface的說明
@interface不是interface,是注解類,是jdk5.0之后加入的
>Override使用說明
- @Override表示指定重寫父類的方法(從編譯層面驗證),如果父類沒有fly方法,則會報錯
- 如果不寫@Override注解,而父類仍有public void fly00,仍然構成重寫
- @Override只能修飾方法,不能修飾其它類,包,屬性等等
- 查看@Override注解原始碼為@Target(ElementType.METHOD),說明只能修飾方法
- @Target是修飾注解的注解,稱為元注解
@Deprecated
@Deprecated的說明
-
用于表示某個程式元素(類,方法等)已過時
-
可以修飾方法,類,欄位,包,引數等等
-
@Target(value=https://www.cnblogs.com/wenjie2000/archive/2022/08/11/{CONSTRUCTOR,FIELD, LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER, TYPE})
-
@Deprecated的作用可以做到新舊版本的兼容和過渡
@Deprecated
class A{
}
@suppresswarnings
@SuppressWarnings:抑制編譯器警告
//關于SuppressWarnings作用范圍是和你放置的位置相關
//看看@SuppressWarnings 原始碼
/*
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
*/
@SuppressWarnings({"unused","unchecked"})
public class Test {
public static void main(String[] args) {
int i;//沒有 @SuppressWarnings({"unused"})會出現黃色警告:i沒有被使用
}
}
>說明各種值
- all是忽略所有警告
- unchecked是忽略沒有檢查的警告
- rawtypes是忽略沒有指定泛型的警告(傳參時沒有指定泛型的警告錯誤)
- unused是忽略沒有使用某個變數的警告錯誤
- 其他關鍵字使用相對較少,需要可自行百度
- @SuppressWarnings可以修飾的程式元素為,查看@Target
- 生成@SupperssWarnings時,不用背,直接點擊左側的黃色提示,就可以選擇(注意可以指定生成的位置)
元注解:對注解進行注解(不重要,僅需了解)
元注解的基本介紹
JDK的元 Annotation用于修飾其他Annotation
元注解:本身作用不大,講這個原因主要用來輔助理解原始碼,看原始碼時,可以知道他是干什么.
元注解的種類(使用不多,了解,不用深入研究)
- Retention //指定注解的作用范圍,三種 SOURCE,CLASS,RUNTIME
- Target //指定注解可以在哪些地方使用
- Documented //指定該注解是否會在javadoc體現
- Inherited //子類會繼承父類注解
Retention注解
說明
只能用于修飾一個 Annotation定義,用于指定該 Annotation可以保留多長時間,@Rentention包含一個 RetentionPolicy型別的成員變數,使用@Rentention時必須為該vajue成員變數指定值:
@Retention的三種值
- RetentionPolicy.SOURCE:編譯器使用后,直接丟棄這種策略的注解
- RetentionPolicy.CLASS:編譯器將把注解記錄在class檔案中.當運行Java程式時,JVM不會保留注解,這是默認值
- RetentionPolicy.RUNTIME:編譯器將把注解記錄在 class 檔案中.當運行Java程式時,JVM會保留注解.程式可以通過反射獲取該注解
@Target
基本說明
用于修飾Annotation定義,用于指定被修飾的Annotation能用于修飾哪些程式元素.@Target也包含一個名為value的成員變數,
原始碼
@Documented
@Retention(RetentionPolicy.RUNTIME)//它的作用范圍是RUNTIME
@Target(ElementType.ANNOTATION_TYPE)//這里的ANNOTATION TYPE 說明@Target只能修飾注解
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();//可以簡單看一下ElementType的取值//通過Enum 比如:TYPE等
}
@Documented
基本說明
@Documented:用于指定被該元 Annotation修飾的Annotation類將被javadoc工具提取成檔案,即在生成檔案時,可以看到該注解,
說明:定義為Documented的注解必須設定Retention值為RUNTIME,
案例
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value=https://www.cnblogs.com/wenjie2000/archive/2022/08/11/{CONSTRUCTOR, FIELD,LOCAL_VARIABLE, METHOD, PACKAGE,PARAMETER, TYPE)
public @interface Deprecated {//一個Deprecated 注解@Documented,則javadoc會看到Deprecated
}
@Inherited
被它修飾的Annotation將具有繼承性.如果某個類使用了被@Inherited修飾的Annotation,則其子類將自動具有該注解
說明:實際應用中,使用較少,了解即可,
元注解:本身作用不大,講這個原因希望編程看原始碼時,可以知道他是干什么,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/501491.html
標籤:其他
