自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

語(yǔ)法糖甜不甜?巧用枚舉實(shí)現(xiàn)“狀態(tài)”轉(zhuǎn)換限制

開(kāi)發(fā) 架構(gòu)
本質(zhì)上,JVM 并不支持語(yǔ)法糖,語(yǔ)法糖只存在于編譯期。當(dāng)編譯器將 .java 源文件編譯成 .class 字節(jié)碼文件時(shí),會(huì)進(jìn)行解語(yǔ)法糖的操作,來(lái)還原最原始的基礎(chǔ)語(yǔ)法結(jié)構(gòu)。

[[423672]]

語(yǔ)法糖

語(yǔ)法糖(Syntactic sugar),也被譯為糖衣語(yǔ)法,是由英國(guó)計(jì)算機(jī)科學(xué)家彼得·約翰·蘭達(dá)(Peter J. Landin)發(fā)明的一個(gè)術(shù)語(yǔ),指計(jì)算機(jī)語(yǔ)言中添加的某種語(yǔ)法,這種語(yǔ)法對(duì)語(yǔ)言的功能并沒(méi)有影響,但是更方便程序員使用。通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì)。——摘抄自百度百科

本質(zhì)上,JVM 并不支持語(yǔ)法糖,語(yǔ)法糖只存在于編譯期。當(dāng)編譯器將 .java 源文件編譯成 .class 字節(jié)碼文件時(shí),會(huì)進(jìn)行解語(yǔ)法糖的操作,來(lái)還原最原始的基礎(chǔ)語(yǔ)法結(jié)構(gòu)。

我們所熟悉的編程語(yǔ)言中幾乎都會(huì)包含語(yǔ)法糖,當(dāng)然 JAVA 也不例外。JAVA 中的語(yǔ)法糖包含條件編譯、斷言、switch 支持 String 與枚舉、可變參數(shù)、自動(dòng)裝箱/拆箱、枚舉、內(nèi)部類、泛型擦除、增強(qiáng)for循環(huán)、lambda表達(dá)式、try-with-resources等等。今天我們先來(lái)了解下枚舉。

枚舉類

JDK5 提供了一種新的特殊的類——枚舉類,一般在類對(duì)象有限且固定的場(chǎng)景下使用,用來(lái)替代類中定義常量的方式。枚舉相較于常量更加直觀且類型安全。

枚舉類的使用非常簡(jiǎn)單,用 enum 關(guān)鍵字來(lái)定義,多個(gè)枚舉變量直接用逗號(hào)隔開(kāi)。我們先來(lái)定義一個(gè)簡(jiǎn)單的枚舉類 OrderStatus.java

  1. public enum OrderStatus { 
  2.     //未支付、已支付、退款中、退款成功、退款失??; 
  3.     NO_PAY, PAY, REFUNDING, REFUNDED, FAIL_REFUNDED, ; 

在其他類中使用 enum 變量的時(shí)候,只需要【類名.變量名】就可以了,和使用靜態(tài)變量一樣。另外,枚舉類型可以確保 JVM 中僅存在一個(gè)常量實(shí)例,所以我們可以放心的使用“ ==”來(lái)比較兩個(gè)變量。

注意事項(xiàng):

枚舉類的第一行必須是枚舉項(xiàng),最后一個(gè)枚舉項(xiàng)后的分號(hào)是可以省略的,但是如果枚舉類有其它的東西,這個(gè)分號(hào)就不能省略。建議不要省略!

枚舉變量最好大寫,多個(gè)單詞之間使用”_”隔開(kāi)(比如:NO_PAY)。

反編譯

我們可以先通過(guò) javac 命令或者 IDEA 的編譯功能將OrderStatus.java 編譯為OrderStatus.class 字節(jié)碼文件,然后用DJ Java Decompiler 反編譯器對(duì) .class 文件進(jìn)行反編譯。

如果需要 DJ Java Decompiler 反編譯器的小伙伴可以私信阿Q獲取!

  1. public final class OrderStatus extends Enum 
  2.  
  3.     //該方法會(huì)返回包括所有枚舉變量的數(shù)組,可以方便的用來(lái)做循環(huán)。 
  4.     public static OrderStatus[] values() 
  5.     { 
  6.         return (OrderStatus[])$VALUES.clone(); 
  7.     } 
  8.  
  9.     //根據(jù)傳入的字符串,轉(zhuǎn)變?yōu)閷?duì)應(yīng)的枚舉變量。 
  10.     //前提是傳的字符串和定義枚舉變量的字符串一抹一樣,區(qū)分大小寫。 
  11.     //如果傳了一個(gè)不存在的字符串,那么會(huì)拋出異常。 
  12.     public static OrderStatus valueOf(String name
  13.     { 
  14.         return (OrderStatus)Enum.valueOf(com/itcast/java/enumpack/OrderStatus, name); 
  15.     } 
  16.  
  17.     private OrderStatus(String s, int i) 
  18.     { 
  19.         super(s, i); 
  20.     } 
  21.  
  22.     public static final OrderStatus NO_PAY; 
  23.     public static final OrderStatus PAY; 
  24.     public static final OrderStatus REFUNDING; 
  25.     public static final OrderStatus REFUNDED; 
  26.     public static final OrderStatus FAIL_REFUNDED; 
  27.     private static final OrderStatus $VALUES[]; 
  28.  
  29.     static  
  30.     { 
  31.         NO_PAY = new OrderStatus("NO_PAY", 0); 
  32.         PAY = new OrderStatus("PAY", 1); 
  33.         REFUNDING = new OrderStatus("REFUNDING", 2); 
  34.         REFUNDED = new OrderStatus("REFUNDED", 3); 
  35.         FAIL_REFUNDED = new OrderStatus("FAIL_REFUNDED", 4); 
  36.         $VALUES = (new OrderStatus[] { 
  37.             NO_PAY, PAY, REFUNDING, REFUNDED, FAIL_REFUNDED 
  38.         }); 
  39.     } 

如源碼所示:

  • 編譯器會(huì)自動(dòng)幫我們創(chuàng)建一個(gè) final 類型的類繼承 Enum 類,所以枚舉類不能被繼承。
  • 會(huì)自動(dòng)生成私有構(gòu)造方法,當(dāng)然我們也可以定義構(gòu)造方法,但必須是私有的,這樣就不能在別處聲明此類的對(duì)象了。
  • 枚舉項(xiàng)會(huì)被自動(dòng)添加 public static final 修飾,并定義為 OrderStatus 類型,并在靜態(tài)代碼塊中被初始化。
  • 并提供了 values() 和 valueOf(String name) 的靜態(tài)方法。

我們定義的枚舉變量實(shí)際上是編譯器幫我們自動(dòng)生成了構(gòu)造函數(shù)。

所有枚舉類都是 Enum 的子類,枚舉類可以實(shí)現(xiàn)一個(gè)或多個(gè)接口。

Enum

Enum 是所有 Java 語(yǔ)言枚舉類型的公共基類,實(shí)現(xiàn)了 Comparable 和 Serializable 接口。它包含 final 類型的 name 和 ordinal (此枚舉常量的序號(hào),從0開(kāi)始)屬性,下面我們來(lái)了解下它的方法

  • protected Enum(String name, int ordinal);——構(gòu)造方法;
  • public String toString();——返回 name 字段,即枚舉定義枚舉變量的字符串;
  • protected final Object clone();——拋出 CloneNotSupportedException 異常,保證枚舉類永遠(yuǎn)不會(huì)被克隆;
  • public final ClassgetDeclaringClass();——返回與此枚舉常量的枚舉類型對(duì)應(yīng)的類對(duì)象;
  • protected final void finalize();—— 枚舉類不能有 finalize 方法;
  • readObject(ObjectInputStream in);& readObjectNoData();—— 拋出InvalidObjectException 異常,防止默認(rèn)反序列化;

擴(kuò)展

枚舉類中可以自定義屬性

自定義的屬性值最好用 private final 修飾,防止生成的 set 方法在使用時(shí)修改屬性值,使代碼更加安全。

枚舉類中可以自定義構(gòu)造函數(shù)

構(gòu)造函數(shù)必須為 private 修飾,防止在別處聲明此類對(duì)象。

枚舉類可以自定義方法,枚舉項(xiàng)可以選擇性覆蓋自定義的方法。

  1. public enum OrderStatus{ 
  2.     NO_PAY("未支付",0), 
  3.     PAY("已支付",1){ 
  4.         @Override 
  5.         public void printOrderStatus() { 
  6.             System.out.println("已支付"); 
  7.         } 
  8.     }, 
  9.     REFUNDING("退款中",2), 
  10.     REFUNDED("退款成功",3), 
  11.     FAIL_REFUNDED("退款失敗",4), 
  12.     ; 
  13.  
  14.     private final String name
  15.     private final int status; 
  16.  
  17.     private OrderStatus(String name,int status){ 
  18.         this.name = name
  19.         this.status = status; 
  20.     } 
  21.  
  22.     public void printOrderStatus(){ 
  23.         System.out.println("打印訂單狀態(tài)"); 
  24.     } 
  25.  
  26.  
  27. public class EnumTest { 
  28.     public static void main(String[] args) { 
  29.         OrderStatus.PAY.printOrderStatus(); 
  30.         OrderStatus.NO_PAY.printOrderStatus(); 
  31.     } 

枚舉類也可以有抽象方法,但是枚舉項(xiàng)必須重寫該方法。

枚舉類實(shí)現(xiàn)接口

與普通類一樣,實(shí)現(xiàn)接口的時(shí)候需要實(shí)現(xiàn)接口的抽象方法,也可以讓枚舉類的不同對(duì)象實(shí)現(xiàn)不同的行為。

  1. //定義一個(gè)接口 
  2. public interface Order { 
  3.     void printOrderStatus(); 
  4.  
  5. //枚舉類實(shí)現(xiàn)該接口 
  6. public enum OrderStatus implements Order
  7.     NO_PAY("未支付",0){ 
  8.         @Override 
  9.         public void printOrderStatus() { 
  10.             System.out.println("未支付"); 
  11.         } 
  12.     }, 
  13.     PAY("已支付",1){ 
  14.         @Override 
  15.         public void printOrderStatus() { 
  16.             System.out.println("已支付"); 
  17.         } 
  18.     }, 
  19.     REFUNDING("退款中",2){ 
  20.         @Override 
  21.         public void printOrderStatus() { 
  22.             System.out.println("退款中"); 
  23.         } 
  24.     }, 
  25.     REFUNDED("退款成功",3){ 
  26.         @Override 
  27.         public void printOrderStatus() { 
  28.             System.out.println("退款成功"); 
  29.         } 
  30.     }, 
  31.     FAIL_REFUNDED("退款失敗",4){ 
  32.         @Override 
  33.         public void printOrderStatus() { 
  34.             System.out.println("退款失敗"); 
  35.         } 
  36.     }, 
  37.     ; 
  38.  
  39.     private final String name
  40.     private final int status; 
  41.  
  42.     private OrderStatus(String name,int status){ 
  43.         this.name = name
  44.         this.status = status; 
  45.     } 

此時(shí)查看編譯后的文件,會(huì)發(fā)現(xiàn)除了生成 OrderStatus.class 文件之外,還生成了多個(gè) .class 文件:

它們是 OrderStatus.class 中生成的匿名內(nèi)部類的文件。

狀態(tài)轉(zhuǎn)換

需求

訂單是電商項(xiàng)目中不可缺少的組成部分,而訂單狀態(tài)的轉(zhuǎn)換也是我們經(jīng)常討論的問(wèn)題。我們都知道訂單狀態(tài)的轉(zhuǎn)換是有一定的邏輯性的,不可以隨意轉(zhuǎn)換。

例:你想購(gòu)買某個(gè)商品,只是把它加入了購(gòu)物車,此時(shí)應(yīng)該是未支付狀態(tài)。如果來(lái)個(gè)請(qǐng)求想把它轉(zhuǎn)換為退款狀態(tài),那么系統(tǒng)應(yīng)該拋出提示信息“狀態(tài)轉(zhuǎn)換失敗,請(qǐng)先完成購(gòu)買!”

接下來(lái)我們就用枚舉來(lái)完成一下訂單狀態(tài)轉(zhuǎn)換的限制。

實(shí)現(xiàn)

枚舉類定義:

  1. public enum OrderStatus{ 
  2.     NO_PAY("未支付",0){ 
  3.         @Override 
  4.         public Boolean canChange(OrderStatus orderStatus) { 
  5.             switch (orderStatus){ 
  6.                 case PAY: 
  7.                     return true
  8.                 default
  9.                     return false
  10.             } 
  11.         } 
  12.     }, 
  13.     PAY("已支付",1){ 
  14.         @Override 
  15.         public Boolean canChange(OrderStatus orderStatus) { 
  16.             //因?yàn)橥丝罱涌谝话愣紩?huì)有延遲,所以會(huì)先轉(zhuǎn)化為“退款中”狀態(tài) 
  17.             switch (orderStatus){ 
  18.                 case REFUNDING: 
  19.                     return true
  20.                 default
  21.                     return false
  22.             } 
  23.         } 
  24.     }, 
  25.     REFUNDING("退款中",2){ 
  26.         @Override 
  27.         public Boolean canChange(OrderStatus orderStatus) { 
  28.             switch (orderStatus){ 
  29.                 case REFUNDED: 
  30.                 case FAIL_REFUNDED: 
  31.                     return true
  32.                 default
  33.                     return false
  34.             } 
  35.         } 
  36.     }, 
  37.     REFUNDED("退款成功",3), 
  38.     FAIL_REFUNDED("退款失敗",4), 
  39.     ; 
  40.  
  41.     private final String name
  42.     private final int status; 
  43.  
  44.     private OrderStatus(String name,int status){ 
  45.         this.name = name
  46.         this.status = status; 
  47.     } 
  48.  
  49.     //自定義轉(zhuǎn)換方法 
  50.     public Boolean canChange(OrderStatus orderStatus){ 
  51.         return false
  52.     } 

調(diào)用方法:

  1. public class EnumTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.         Boolean aBoolean = OrderStatus.NO_PAY.canChange(OrderStatus.PAY); 
  5.         String statusStr = aBoolean?"可以":"不可以"
  6.         System.out.println("是否可以完成狀態(tài)轉(zhuǎn)換:"+ statusStr); 
  7.  
  8.         Boolean flag = OrderStatus.REFUNDED.canChange(OrderStatus.FAIL_REFUNDED); 
  9.         String flagStr = flag?"可以":"不可以"
  10.         System.out.println("是否可以完成狀態(tài)轉(zhuǎn)換:"+ flagStr); 
  11.     } 

返回結(jié)果:

 

這樣我們就用枚舉類實(shí)現(xiàn)了訂單狀態(tài)轉(zhuǎn)換的限制。此例子只是為狀態(tài)轉(zhuǎn)換提供一種思路,具體的流程還需要根據(jù)自己系統(tǒng)中的業(yè)務(wù)來(lái)具體處理。

 

責(zé)任編輯:武曉燕 來(lái)源: 阿Q說(shuō)代碼
相關(guān)推薦

2016-06-02 15:10:12

SwiftSelector

2020-12-08 07:51:53

Java語(yǔ)法糖泛型

2016-10-14 14:04:34

JAVA語(yǔ)法main

2024-09-11 16:34:38

語(yǔ)法糖Java語(yǔ)言

2022-02-14 08:04:02

Go語(yǔ)法糖編譯器

2010-01-22 17:55:23

VB.NET語(yǔ)法糖

2024-10-11 15:04:35

KafkaLeader選舉

2019-05-23 11:42:04

Java語(yǔ)法糖編程語(yǔ)言

2022-02-17 13:46:15

SSH命令內(nèi)網(wǎng)

2023-09-11 08:20:17

對(duì)象閉包底層

2009-08-18 12:52:33

C#枚舉類型

2019-06-05 13:05:47

PHP語(yǔ)法糖編碼

2022-08-04 14:38:49

vue3.2setup代碼

2023-09-01 10:00:17

2024-10-31 15:16:35

2011-08-08 12:44:30

IP安全策略遠(yuǎn)程登錄

2012-03-31 16:42:24

2019-05-14 14:51:40

Java語(yǔ)法糖用法

2024-03-15 08:45:31

Vue 3setup語(yǔ)法

2018-07-30 16:32:25

應(yīng)屆生認(rèn)知誤區(qū)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)