學習JavaEE的日子 Day21 枚舉

Day21

1.枚舉的引入

需求:編寫季節類(Season),該類只有四個對象(spring,summer,autumn,winter)

概念:枚舉(enum)全稱為 enumeration, 是 JDK 1.5 中引入的新特性。

public enum Color{//默認添加 public static finalRED,GREEN,BLUE;
} 

本質:盡管枚舉看起來像是一種新的數據類型,實際上,枚舉就是一種受限制的類,并且具有自己的方法。創建自己的enum類時,這個類繼承自 java.lang.Enum。


public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable{...
}

特點

  • 枚舉就是一個受限制的類,默認繼承Enum
  • 枚舉的第一行必須定義該枚舉類型的對象
  • 枚舉類型對象默認添加: public static final 類型
  • 枚舉沒有繼承明確類(自定義枚舉類默認繼承Enum,Enum默認繼承Object)
  • 枚舉類不能被繼承
  • 枚舉里可以有構造方法、成員方法、靜態方法、抽象方法
  • 枚舉可以實現接口
  • 枚舉里沒有定義方法,可以在最后一個對象后面加逗號、分號或什么都不加

優勢

  • 增強代碼可讀性

  • 枚舉型可直接與數據庫交互

  • switch語句優勢

  • 編譯優勢

(枚舉類編譯時,沒有把常量值編譯到代碼中,即使常量值發生改變,也不會影響引用常量的類 )

  • 將常量組織起來,統一管理

  • 去除equals兩者判斷 由于常量值地址唯一,使用枚舉可以直接通過“==”進行兩個值之間的對比,性能會有所提高

經驗:一個類有固定幾個對象,就用枚舉代替

常規寫法:

public class Test01 {public static void main(String[] args) {Season spring = Season.spring;Season summer = Season.summer;Season autumn = Season.autumn;Season winter = Season.winter;System.out.println(spring);System.out.println(summer);System.out.println(autumn);System.out.println(winter);}
}
public class Season {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("冬天", "銀裝素裹");private String name;private String info;private Season() {}private Season(String name, String info) {this.name = name;this.info = info;}// get,set,toString省略
}

枚舉寫法:

注意:使用枚舉來解決該需求

經驗:一個類有固定幾個對象,就用枚舉代替

public class Test01 {public static void main(String[] args) {Season spring = Season.spring;Season summer = Season.summer;Season autumn = Season.autumn;Season winter = Season.winter;System.out.println(spring);System.out.println(summer);System.out.println(autumn);System.out.println(winter);}
}
//注意:枚舉就是一個特殊的類,但是他也是引用數據類型的一種
//注意:枚舉沒有顯示繼承
//注意:枚舉有隱式繼承 -> Season extends Enum extends Object
public enum Season{//注意:枚舉類第一行必須聲明對象//注意:枚舉對象默認使用public static final修飾 -- public static final Season spring = new Season("春天","春雨綿綿");spring("春天","春雨綿綿"),summer("夏天","烈日炎炎"),autumn("秋天","碩果累累"),winter("冬天","白雪皚皚");private String name;private String info;//注意:枚舉類的構造方法都是私有的private Season() {}private Season(String name, String info) {this.name = name;this.info = info;}//get,set,toString省略
}

2.枚舉的常用方法

方法名解釋
Enum.valueOf(Class enumType, String name)根據字符串找到該枚舉類中的對象
public static void values()獲取該枚舉類對象數組
public static void valueOf(String args0)根據字符串獲取該枚舉類中的對象
public class Test02 {public static void main(String[] args) {//通過字符串獲取枚舉類中的對象Season season1 = Enum.valueOf(Season.class, "spring");System.out.println(season1);//通過字符串獲取枚舉類中的對象Season season2 = Season.valueOf("spring");System.out.println(season2);//獲取Season枚舉類中所有的對象,返回數組Season[] values = Season.values();for (Season season : values) {System.out.println(season);}}
}

3.手撕枚舉底層源碼

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {private final String name;//枚舉對象名private final int ordinal;//枚舉編號(從0開始)protected Enum(String name, int ordinal) {this.name = name;this.ordinal = ordinal;}}
//枚舉本質意義上就是一個類,默認繼承Enum
public final class Season extends Enum{public static final Season spring;public static final Season summer;public static final Season autumn;public static final Season winter;private String name;private String info;//存放該枚舉類的所有對象 -- 數組private static final Season[] ENUM$VALUES;//靜態代碼塊(初始化枚舉對象、將枚舉對象存入ENUM$VALUES數組中)static{spring = new Season("spring", 0, "春天", "春雨綿綿");summer = new Season("summer", 1, "夏天", "烈日炎炎");autumn = new Season("autumn", 2, "秋天", "碩果累累");winter = new Season("winter", 3, "冬天", "白雪皚皚");ENUM$VALUES = (new Season[] {spring, summer, autumn, winter});}//改造了我們寫的無參構造 -- private Season(){}private Season(String s, int i){super(s, i);}//改造了我們寫的有參構造 -- private Season(String name,String info){}private Season(String s, int i, String name, String info){super(s, i);this.name = name;this.info = info;}//get,set省略public String toString(){return (new StringBuilder(String.valueOf(name))).append(" -- ").append(info).toString();}public static Season[] values(){Season[] aseason = ENUM$VALUES;//獲取ENUM$VALUESint i  = aseason.length;//i - 4//創建了一個與ENUM$VALUES長度相同的數組Season[] aseason1 = new Season[i];System.arraycopy(aseason, 0, aseason1, 0, i);return aseason1;}public static Season valueOf(String s){return (Season)Enum.valueOf(com/qf/enum02/Season, s);}}

4.面試題

4.1 研究switch如何判斷枚舉類型

注意:底層會創建一個枚舉個數的數組 – ai[1,2,3,4]

public class Test03 {public static void main(String[] args) {switch (Season.spring) {case spring:System.out.println("春天");break;case summer:System.out.println("夏天");break;case autumn:System.out.println("秋天");break;case winter:System.out.println("冬天");break;}}
}

底層源碼

public class Test03{private static int[] $SWITCH_TABLE$com$qf$enum02$Season;//[1,2,3,4]public static void main(String args[]){//[1,2,3,4]int[] ai = $SWITCH_TABLE$com$qf$enum02$Season();switch (ai[Season.spring.ordinal()]){//ai[0] -- 1case 1: // '\001'System.out.println("春天");break;case 2: // '\002'System.out.println("夏天");break;case 3: // '\003'System.out.println("秋天");break;case 4: // '\004'System.out.println("冬天");break;}}static int[] $SWITCH_TABLE$com$qf$enum02$Season(){//[0,0,0,0]int[] ai = new int[Season.values().length];//Season.values().length - 4try{//Season.autumn.ordinal() -- 2ai[Season.autumn.ordinal()] = 3;//ai[2] = 3;}catch (NoSuchFieldError ) { }try{//Season.spring.ordinal() - 0ai[Season.spring.ordinal()] = 1;//ai[0] = 1}catch (NoSuchFieldError ) { }try{//Season.summer.ordinal - 1ai[Season.summer.ordinal()] = 2;//ai[1] = 2}catch (NoSuchFieldError ) { }try{//Season.winter.ordinal() - 3ai[Season.winter.ordinal()] = 4;//ai[3] = 4}catch (NoSuchFieldError ) { }//ai -> [1,2,3,4]return $SWITCH_TABLE$com$qf$enum02$Season = ai;}
}

4.2 研究switch如何判斷String類型

注意:底層原理就是先判斷hash值,然后再判斷兩個字符串是否相同(equals)

public class Test04 {public static void main(String[] args) {switch ("abc") {case "abc":System.out.println("abc");break;case "def":System.out.println("def");break;case "zyx":System.out.println("xyz");break;}}
}

底層源碼

//研究String的hash值是如何算出來的
String str = "abc";public class String{final char[] value;//['a','b','c']public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char[] val = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}}
public class Test04{public static void main(String args[]){String s;switch ((s = "abc").hashCode()){//96354case 96354://"abc".hashCode();if (s.equals("abc"))System.out.println("abc");break;case 99333: //"def".hashCode();if (s.equals("def"))System.out.println("def");break;case 121113: //"zyx".hashCode();if (s.equals("zyx"))System.out.println("xyz");break;}}
}

補:hash值一樣,不需要if判斷可以嗎?

public class Test05 {/*** 知識點:研究switch如何判斷String類型* * 注意:底層原理就是先判斷hash值,然后再判斷兩個字符串是否相同(equals)*/public static void main(String[] args) {System.out.println("Aa".hashCode());System.out.println("BB".hashCode());switch ("Aa") {case "BB":System.out.println("BB");break;case "Aa":System.out.println("Aa");break;case "zyx":System.out.println("xyz");break;}}
}
public class Test05{public static void main(String args[]){String s;switch ((s = "Aa").hashCode()){//2112case 2112: //"BB".hashCode() -- "Aa".hashCode()if (!s.equals("BB")){if (s.equals("Aa"))System.out.println("Aa");} else{System.out.println("BB");}break;case 121113: if (s.equals("zyx"))System.out.println("xyz");break;}}
}

5.枚舉案例 之 狀態機

//信號燈的枚舉
public enum Signal {RED,YELLOW,GREEN;
}
public class Test01 {public static void main(String[] args) {Scanner scan = new Scanner(System.in);System.out.println("請選擇信號燈:RED、YELLOW、GREEN");String str = scan.next();Signal signal = Signal.valueOf(str);String trafficInstruct = getTrafficInstruct(signal);System.out.println(trafficInstruct);scan.close();}public static String getTrafficInstruct(Signal signal){String instruct = "信號燈故障";switch (signal) {case RED:instruct = "紅燈停";break;case YELLOW:instruct = "黃燈請注意";break;case GREEN:instruct = "綠燈行";break;}return instruct;}
}

6.枚舉案例 之 錯誤碼/狀態碼

public enum AddCode {ERR_1(-1,"添加失敗 - 學生信息不合法"),ERR_2(-2,"添加失敗 - 有該學生"),OK(1,"添加成功");private int code;private String message;private AddCode() {}private AddCode(int code, String message) {this.code = code;this.message = message;}//get,set,toString省略
}
public class Test01 {public static void main(String[] args) {System.out.println(AddCode.ERR_1.getCode());System.out.println(AddCode.ERR_1.getMessage());System.out.println(AddCode.ERR_1);}
}

7.枚舉案例 之 組織枚舉

應用場景:把一些同類別的枚舉使用類或接口組織起來

注意:一般使用接口去組織多個枚舉

原因:

使用類去組織枚舉,類里的枚舉默認添加static修飾 – 靜態內部類

使用接口去組織枚舉,接口的枚舉默認添加public static修飾 – 接口內部類(公有靜態內部類)

就是說,在類中組織 enum,如果你不給它修飾為 public,那么只能在本包中進行訪問。

? 考慮到其他包中還可以使用到枚舉對象,所以推薦使用接口去組織

public interface Code {enum UpdateCode {ERR_1(-1,"修改失敗 -- 學生信息不合法"),ERR_2(-2,"修改失敗 -- 沒有該學生"),ERR_3(-3,"修改失敗 -- 修改值的信息不合法"),ERR_4(-4,"修改失敗 -- 目標班級上有學生"),ERR_5(-5,"修改失敗 -- 目標學號上有學生"),OK(1,"修改成功");private int code;private String message;private UpdateCode() {}private UpdateCode(int code, String message){this.code = code;this.message = message;}//get,set,toString省略}}

8.枚舉案例 之 策略枚舉

優點:這種枚舉通過枚舉嵌套枚舉的方式,將枚舉常量分類處理。

這種做法雖然沒有switch語句簡潔,但是更加安全、靈活。

需求:模擬公司計算工資的功能

分析:

員工類別:行政、講師

部門:Java(講師)、Python(講師)、HTML(講師)、總經辦(行政)、人力(行政)、財務(行政)

行政工資構成:基本工資 + 績效

講師工資構成:基本工資 + 績效 + 課時費*課時

//public final class QianFeng extends Enum
public enum QianFeng {Java(StaffType.teacher),Python(StaffType.teacher),HTML(StaffType.teacher),GeneralManagerOffice(StaffType.admin),HR(StaffType.admin),finance(StaffType.admin);private StaffType staffType;private QianFeng(StaffType staffType) {this.staffType = staffType;}public double getSalary(double basicSalary, double performance, double classFees, double classHours){return staffType.calculateSalary(basicSalary, performance, classFees, classHours);}//員工類型//public static abstract class QianFeng$StaffType extends Enumpublic enum StaffType{//class QianFeng$StaffType$1 extends QianFeng$StaffType//QianFeng$StaffType$1 admin = QianFeng$StaffType$1(){//	@Override//	public double calculateSalary(double basicSalary, double performance, double classFees, double classHours) {//		return 0;//	}//}admin {//行政類別@Overridepublic double calculateSalary(double basicSalary, double performance, double classFees, double classHours) {BigDecimal big1 = new BigDecimal(String.valueOf(basicSalary));BigDecimal big2 = new BigDecimal(String.valueOf(performance));double salary = big1.add(big2).doubleValue();return salary;}},//class QianFeng$StaffType$2 extends QianFeng$StaffType//QianFeng$StaffType$2 teacher = QianFeng$StaffType$2(){//	@Override//	public double calculateSalary(double basicSalary, double performance, double classFees, double classHours) {//		return 0;//	}//}teacher {@Overridepublic double calculateSalary(double basicSalary, double performance, double classFees, double classHours) {BigDecimal big1 = new BigDecimal(String.valueOf(basicSalary));BigDecimal big2 = new BigDecimal(String.valueOf(performance));BigDecimal big3 = new BigDecimal(String.valueOf(classFees));BigDecimal big4 = new BigDecimal(String.valueOf(classHours));double salary = big3.multiply(big4).add(big1).add(big2).doubleValue();return salary;}};public abstract double calculateSalary(double basicSalary, double performance, double classFees, double classHours);}
}
public class Test01 {public static void main(String[] args) {double salary1 = QianFeng.Java.getSalary(1800, 200, 88, 9);System.out.println(salary1);double salary2 = QianFeng.GeneralManagerOffice.getSalary(50000, 30000, 0, 0);System.out.println(salary2);}
}

總結

1.枚舉特點,優勢

2.枚舉的常用方法

3.底層原理

4.面試題

5.枚舉案例
狀態機
錯誤碼
組織枚舉
策略枚舉 — 難點

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713843.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713843.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713843.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基帶信號處理設計原理圖:2-基于6U VPX的雙TMS320C6678+Xilinx FPGA K7 XC7K420T的圖像信號處理板

基于6U VPX的雙TMS320C6678Xilinx FPGA K7 XC7K420T的圖像信號處理板 綜合圖像處理硬件平臺包括圖像信號處理板2塊&#xff0c;視頻處理板1塊&#xff0c;主控板1塊&#xff0c;電源板1塊&#xff0c;VPX背板1塊。 一、板卡概述 圖像信號處理板包括2片TI 多核DSP處理…

Linux進程管理:(二)進程調度原語

文章說明&#xff1a; Linux內核版本&#xff1a;5.0 架構&#xff1a;ARM64 參考資料及圖片來源&#xff1a;《奔跑吧Linux內核》 Linux 5.0內核源碼注釋倉庫地址&#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 進程調度的概念比較簡單&#xff0c…

Java學習筆記NO.17

T1&#xff1a;合并兩個排序好的整數數組 import java.util.Arrays;public class MergeSortedArrays {public static int[] mergeArrays(int[] arr1, int[] arr2) {int[] result new int[arr1.length arr2.length];int i 0, j 0, k 0;while (i < arr1.length &&am…

一個簡單的iOS天氣應用程序源碼

創建一個簡單的iOS天氣應用程序涉及到多個步驟&#xff0c;包括設置項目、編寫代碼和使用外部API。由于篇幅限制&#xff0c;我將提供一個基礎的示例&#xff0c;這個例子會展示如何創建一個簡單的UI&#xff0c;獲取用戶的當前位置&#xff0c;并從OpenWeatherMap API獲取天氣…

QPS 提升 10 倍!滴滴借助 StarRocks 物化視圖實現低成本精確去重

作者&#xff1a;滴滴 OLAP 開發工程師 劉雨飛 小編導讀&#xff1a; 滴滴于 2022 年引入了 StarRocks。經過一年多的努力&#xff0c;StarRocks 逐漸替代了原有技術棧&#xff0c;成為滴滴內部主要的 OLAP 引擎。截至 2023 年 12 月&#xff0c;滴滴已經成功建立了超過 40 個 …

Cesium插件系列——3dtiles壓平

本系列為自己基于cesium寫的一套插件具體實現。 這里是根據Cesium提供的CustomShader來實現的。 在CustomShader的vertexShaderText里&#xff0c;需要定義vertexMain函數&#xff0c;例如下&#xff1a; struct VertexInput {Attributes attributes;FeatureIds featureIds;…

LVGL常用部件使用總結之圖片部件

圖片部件可用于顯示圖片&#xff0c;圖片源可以是 C 語言數組格式的文件、二進制的.bin 文件以及圖標字體。值得注意的是&#xff0c;圖片部件要顯示 BMP、JPEG 等格式的圖片&#xff0c;則必須經過解碼。 圖片部件的組成部分僅有一個&#xff1a;主體&#xff08;LV_PART_MAIN…

URI到底是個啥

URI是統一資源標識符&#xff08;Uniform Resource Identifier&#xff09;&#xff0c;URL是統一資源定位符&#xff08;Uniform Resource Locator&#xff09;。 具體如何標記和區分服務器上的資源用的其實就是URI&#xff0c;因為其經常出現在瀏覽器的地址欄里&#xff0c;…

Verilog(未完待續)

Verilog教程 這個教程寫的很好&#xff0c;可以多看看。本篇還沒整理完。 一、Verilog簡介 什么是FPGA&#xff1f;一種可通過編程來修改其邏輯功能的數字集成電路&#xff08;芯片&#xff09; 與單片機的區別&#xff1f;對單片機編程并不改變其地電路的內部結構&#xff0…

Parallel Computing - 一文講懂并行計算

目錄 Throughput/LatencySerial ComputingParallel ComputingTypes of parallel computersSimple 4-width SIMDAmdahls lawTypes of parallelism**Data Parallel Model**Task parallel PartitioningDomain DecompositionFunctional Decomposition CommunicationsExample that d…

java調用chatgpt接口,實現專屬于自己的人工智能助手

文章目錄 前言導包基本說明請求參數響應參數創建請求和響應的VO類 代碼編寫使用最后說明 前言 今天突然突發奇想&#xff0c;就想要用java來調用chatget的接口&#xff0c;實現自己的聊天機器人&#xff0c;但是網上找文章&#xff0c;屬實是少的可憐(可能是不讓發吧)。找到了…

ESP32 web 對接華為云平臺--MQTT協議

文章目錄 前言一、MQTT協議二、如何使用MQTT協議對接華為云1.注冊華為云賬號2.設備接入中創建資源空間3.如何連接4.通過MQTT.fx工具做初步對接4.1 設置連接信息4.2 連接平臺 5.查看平臺設備信息 三. 設備測對接平臺1.ESP測引入MQTT庫2.編碼2.1前端編碼修改2.2 后端接口修改 3.M…

element-plus+vue3表單含圖片(可預覽)(線上圖片)

一、要實現的效果&#xff1a; 二、如果期間出現這樣的效果&#xff08;表格穿透過來了&#xff09;&#xff0c;加上了這行代碼就可以了&#xff1a; preview-teleported“true” 如果僅測試用&#xff0c;建議使用線上圖片鏈接的形式&#xff0c;免得本地地址不生效&#xf…

SSH 的兩種認證方式

SSH&#xff08;Secure Shell&#xff09;提供了幾種不同的認證方式&#xff0c;其中兩種最常見的方式是密碼認證和密鑰認證。以下是它們的詳細介紹&#xff1a; 密碼認證&#xff1a; 原理&#xff1a;用戶在連接時輸入用戶名和密碼&#xff0c;然后將密碼傳輸到遠程服務器進行…

數學實驗-Matlab使用(1)

使用方法以及筆記均在文件中 class1_func1.m function f class1_func1(x) % f為輸出&#xff0c;輸出有多個時需要用中括號以矩陣的方式包起來 % x為輸入f sin(x)class1_func2.m function [a,b,u,v] class1_func2(x,y)[a,b] eig(x)[u,v] eig(y)class1.m % 當語句后有…

yolov9從頭開始訓練

yolov9從頭開始訓練 一、準備數據集 數據集相關文件存放布局如下 yolov9-datasets ├── train │ ├── images │ │ ├── image.jpg │ │ ├── │ └── labels │ ├── image.txt │ ├── ├── valid │ ├── images │ │ ├── image.jpg │ │ ├─…

吳恩達deeplearning.ai:模型選擇交叉驗證測試集的訓練方法

以下內容有任何不理解可以翻看我之前的博客哦&#xff1a;吳恩達deeplearning.ai專欄 在上一節中&#xff0c;我們了解了如何利用測試集來評估模型性能。今天我們來進一步完善這個想法&#xff0c;讓你使用該技術自動選擇一個更好的模型。 文章目錄 模型選擇交叉驗證 Cross Va…

SpringBoot 框架(上)

SpringBoot SpringBoot概述依賴管理自動配置SpringBoot 注解使用ConfigurationImport(value {Cat.class,Dog.class})ImportResource(locations "classpath:beans.xml") yaml 標記語言概述基本語法數據類型字面量對象數組 使用細節 Rest 風格請求處理概述注意事項 接…

vue2 開發記錄

el-select 如何修改選擇項的樣式/el-select-dropdown__item 文字上下顯示 測試代碼 <div stylemargin-left: 100px><!-- 測試代碼--><el-select filterablesizemini><div classxxx-el-select><el-optionv-foritem in [{key:1,des:2,…

AVT Prosilica GC Vision Cameras 相機視覺說明使用安裝。具體詳情內容可參看PDF目錄內容。

AVT Prosilica GC Vision Cameras 相機視覺說明使用安裝。具體詳情內容可參看PDF目錄內容。