语法糖

语法糖(Syntactic sugar),也被译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。——摘抄自百度百科

本质上,JVM 并不支持语法糖,语法糖只存在于编译期。当编译器将 .java 源文件编译成 .class 字节码文件时,会进行解语法糖的操作,来还原最原始的基础语法结构。

我们所熟悉的编程语言中几乎都会包含语法糖,当然 JAVA 也不例外。JAVA 中的语法糖包含条件编译断言switch 支持 String 与枚举可变参数自动装箱/拆箱枚举内部类泛型擦除增强for循环lambda表达式try-with-resources等等。今天我们先来了解下枚举

 

枚举类

JDK5 提供了一种新的特殊的类——枚举类,一般在类对象有限且固定的场景下使用,用来替代类中定义常量的方式。枚举相较于常量更加直观且类型安全。

枚举类的使用非常简单,用 enum 关键字来定义,多个枚举变量直接用逗号隔开。我们先来定义一个简单的枚举类 OrderStatus.java

public enum OrderStatus {//未支付、已支付、退款中、退款成功、退款失败;NO_PAY, PAY, REFUNDING, REFUNDED, FAIL_REFUNDED, ;
}

在其他类中使用 enum 变量的时候,只需要【类名.变量名】就可以了,和使用静态变量一样。另外,枚举类型可以确保 JVM 中仅存在一个常量实例,所以我们可以放心的使用“ ==”来比较两个变量。

注意事项:

  1. 枚举类的第一行必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其它的东西,这个分号就不能省略。建议不要省略!

  2. 枚举变量最好大写,多个单词之间使用”_”隔开(比如:NO_PAY)。

反编译

我们可以先通过 javac 命令或者 IDEA 的编译功能将OrderStatus.java 编译为OrderStatus.class 字节码文件,然后用DJ Java Decompiler 反编译器对 .class 文件进行反编译。

如果需要 DJ Java Decompiler 反编译器的小伙伴可以私信阿Q获取!

public final class OrderStatus extends Enum
{//该方法会返回包括所有枚举变量的数组,可以方便的用来做循环。public static OrderStatus[] values(){return (OrderStatus[])$VALUES.clone();}//根据传入的字符串,转变为对应的枚举变量。//前提是传的字符串和定义枚举变量的字符串一抹一样,区分大小写。//如果传了一个不存在的字符串,那么会抛出异常。public static OrderStatus valueOf(String name){return (OrderStatus)Enum.valueOf(com/itcast/java/enumpack/OrderStatus, name);}private OrderStatus(String s, int i){super(s, i);}public static final OrderStatus NO_PAY;public static final OrderStatus PAY;public static final OrderStatus REFUNDING;public static final OrderStatus REFUNDED;public static final OrderStatus FAIL_REFUNDED;private static final OrderStatus $VALUES[];static {NO_PAY = new OrderStatus("NO_PAY", 0);PAY = new OrderStatus("PAY", 1);REFUNDING = new OrderStatus("REFUNDING", 2);REFUNDED = new OrderStatus("REFUNDED", 3);FAIL_REFUNDED = new OrderStatus("FAIL_REFUNDED", 4);$VALUES = (new OrderStatus[] {NO_PAY, PAY, REFUNDING, REFUNDED, FAIL_REFUNDED});}
}

如源码所示:

  • 编译器会自动帮我们创建一个 final 类型的类继承 Enum 类,所以枚举类不能被继承。

  • 会自动生成私有构造方法,当然我们也可以定义构造方法,但必须是私有的,这样就不能在别处声明此类的对象了。

  • 枚举项会被自动添加 public static final 修饰,并定义为 OrderStatus 类型,并在静态代码块中被初始化。

  • 并提供了 values()valueOf(String name) 的静态方法。

我们定义的枚举变量实际上是编译器帮我们自动生成了构造函数。

所有枚举类都是 Enum 的子类,枚举类可以实现一个或多个接口。

Enum

Enum 是所有 Java 语言枚举类型的公共基类,实现了 Comparable 和 Serializable 接口。它包含 final 类型的 name 和 ordinal (此枚举常量的序号,从0开始)属性,下面我们来了解下它的方法

  • protected Enum(String name, int ordinal);——构造方法;

  • public String toString();——返回 name 字段,即枚举定义枚举变量的字符串;

  • protected final Object clone();——抛出 CloneNotSupportedException 异常,保证枚举类永远不会被克隆;

  • public final ClassgetDeclaringClass();——返回与此枚举常量的枚举类型对应的类对象;

  • protected final void finalize();—— 枚举类不能有 finalize 方法;

  • readObject(ObjectInputStream in);& readObjectNoData();—— 抛出InvalidObjectException 异常,防止默认反序列化;

扩展

  1. 枚举类中可以自定义属性

    自定义的属性值最好用 private final 修饰,防止生成的 set 方法在使用时修改属性值,使代码更加安全。

  2. 枚举类中可以自定义构造函数

    构造函数必须为 private 修饰,防止在别处声明此类对象。

  3. 枚举类可以自定义方法,枚举项可以选择性覆盖自定义的方法。

    public enum OrderStatus{NO_PAY("未支付",0),PAY("已支付",1){@Overridepublic void printOrderStatus() {System.out.println("已支付");}},REFUNDING("退款中",2),REFUNDED("退款成功",3),FAIL_REFUNDED("退款失败",4),;private final String name;private final int status;private OrderStatus(String name,int status){this.name = name;this.status = status;}public void printOrderStatus(){System.out.println("打印订单状态");}
    }public class EnumTest {public static void main(String[] args) {OrderStatus.PAY.printOrderStatus();OrderStatus.NO_PAY.printOrderStatus();}
    }

枚举类也可以有抽象方法,但是枚举项必须重写该方法。

  1. 枚举类实现接口

    与普通类一样,实现接口的时候需要实现接口的抽象方法,也可以让枚举类的不同对象实现不同的行为。

//定义一个接口
public interface Order {void printOrderStatus();
}//枚举类实现该接口
public enum OrderStatus implements Order{NO_PAY("未支付",0){@Overridepublic void printOrderStatus() {System.out.println("未支付");}},PAY("已支付",1){@Overridepublic void printOrderStatus() {System.out.println("已支付");}},REFUNDING("退款中",2){@Overridepublic void printOrderStatus() {System.out.println("退款中");}},REFUNDED("退款成功",3){@Overridepublic void printOrderStatus() {System.out.println("退款成功");}},FAIL_REFUNDED("退款失败",4){@Overridepublic void printOrderStatus() {System.out.println("退款失败");}},;private final String name;private final int status;private OrderStatus(String name,int status){this.name = name;this.status = status;}
}

此时查看编译后的文件,会发现除了生成 OrderStatus.class 文件之外,还生成了多个 .class 文件:

它们是 OrderStatus.class 中生成的匿名内部类的文件。

 

状态转换

需求

订单是电商项目中不可缺少的组成部分,而订单状态的转换也是我们经常讨论的问题。我们都知道订单状态的转换是有一定的逻辑性的,不可以随意转换。

:你想购买某个商品,只是把它加入了购物车,此时应该是未支付状态。如果来个请求想把它转换为退款状态,那么系统应该抛出提示信息“状态转换失败,请先完成购买!”

接下来我们就用枚举来完成一下订单状态转换的限制。

实现

枚举类定义:

public enum OrderStatus{NO_PAY("未支付",0){@Overridepublic Boolean canChange(OrderStatus orderStatus) {switch (orderStatus){case PAY:return true;default:return false;}}},PAY("已支付",1){@Overridepublic Boolean canChange(OrderStatus orderStatus) {//因为退款接口一般都会有延迟,所以会先转化为“退款中”状态switch (orderStatus){case REFUNDING:return true;default:return false;}}},REFUNDING("退款中",2){@Overridepublic Boolean canChange(OrderStatus orderStatus) {switch (orderStatus){case REFUNDED:case FAIL_REFUNDED:return true;default:return false;}}},REFUNDED("退款成功",3),FAIL_REFUNDED("退款失败",4),;private final String name;private final int status;private OrderStatus(String name,int status){this.name = name;this.status = status;}//自定义转换方法public Boolean canChange(OrderStatus orderStatus){return false;}
}

调用方法:

public class EnumTest {public static void main(String[] args) {Boolean aBoolean = OrderStatus.NO_PAY.canChange(OrderStatus.PAY);String statusStr = aBoolean?"可以":"不可以";System.out.println("是否可以完成状态转换:"+ statusStr);Boolean flag = OrderStatus.REFUNDED.canChange(OrderStatus.FAIL_REFUNDED);String flagStr = flag?"可以":"不可以";System.out.println("是否可以完成状态转换:"+ flagStr);}
}

返回结果:

这样我们就用枚举类实现了订单状态转换的限制。此例子只是为状态转换提供一种思路,具体的流程还需要根据自己系统中的业务来具体处理。

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

语法糖甜不甜?巧用枚举实现“状态”转换限制相关推荐

  1. C语言基本语法——结构体、联合和枚举

    一.结构体 1.什么是结构体 2.结构体语法格式 3.结构体所占内存空间 4.结构体成员赋值 二.联合 1.什么是联合 2.联合语法格式 三.枚举 1.什么是枚举 2.枚举语法格式 一.结构体 1.什 ...

  2. 替代if else 的方法---巧用枚举类和抽象方法

    替代if else 的方法-巧用枚举类和抽象方法 使用场景:当接收到一些数据需要对其进行处理时,由于它们来自于不同的渠道(如:腾讯,巨量),不同渠道所需的处理方式不同,下面来写一个简单Demo来展示. ...

  3. 什么叫枚举法_四年级:美妙数学之“巧用枚举法”1(0202四)

    美妙数学天天见 每天进步多一点 亲爱的小朋友,你好!我是朱乐平数学名师工作站的赵桂华老师,来自重庆市沙坪坝区西永第一小学. 准备好了吗?我们开始吧! 聪明的小朋友,你愿意和天天一起动脑思考吗? 天天, ...

  4. 你知道 Java 中关键字 enum 是一个语法糖吗?反编译枚举类

    奇怪的开始 他最初的问题,把我问的完全摸不着头脑 当时我看到就很懵~ 给了一个当时的第一印象的回答 (图片说明:两个打错别字的憨憨) 随后他手敲了代码扔给了我~ 奇怪的代码 接口信息 /*** 可自描 ...

  5. 牛客竞赛语法入门班数组模拟、枚举、贪心习题【未完结】

    题目地址: https://ac.nowcoder.com/acm/contest/19851?from=acdiscuss 目录 四舍五入 安卓图案解锁 Captcha Cracker 回文数 [N ...

  6. 巧用枚举CommandBehavior关闭SqlDataReader联接数据库时的conn.open状态

    编码过程中使用SqlDataReader 来操作数据库时,你是否每次在调用完你的数据库方法后,再手动调用方法或写代码关闭数据库联接呢?(呵呵 我以前是这样做的 见笑) 下面的方法可以完成解决此问题了, ...

  7. 枚举 + 进制转换 --- hdu 4937 Lucky Number

    Lucky Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) T ...

  8. BZOJ1688|二进制枚举子集| 状态压缩DP

    Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) ...

  9. UVa LA 4253 UVa 1421 Archery 枚举,状态削减,oj错误题目 难度: 1

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

最新文章

  1. 渗透测试:正义黑客的渗透测试以及该过程和黑客活动的区别
  2. 三维感知,这些干货足够了!(自动驾驶/三维重建/SLAM/点云/标定/深度估计/3D检测)...
  3. UA MATH564 概率论 QE练习题1
  4. spark知识点八万字长文最全汇总和高频面试题目
  5. java-StringBuffer构造方法
  6. [tensorflow] - csv文件读取
  7. P3403 跳楼机 同余最短路
  8. 苹果发布新应用Find My Friends,轻松追踪朋友和家人的所在位置
  9. Python Imaging Library: ImageStat Module(图像统计模块)
  10. python shell清屏指令_python shell怎么清屏
  11. 四十个鹏城春夏,一场数字繁花
  12. Glib基础——版本信息
  13. 微软面试题--三个灯泡--三个开关
  14. ARM汇编指令(B/BL/BX)
  15. html文字居中加下划线,HTML文字对齐,斜体,下划线和删除线
  16. 潘石屹陈志武谈房地产:北京等城市泡沫已很严重(载自新浪)
  17. NNDL 实验七 循环神经网络(3)LSTM的记忆能力实验
  18. 王道计算机网络第三章
  19. 区块链随想录——BitCoin的未来会如何?
  20. 一键GHOST硬盘版安装使用教程

热门文章

  1. 聚类算法的缺点_常用聚类算法
  2. display none的元素重新展示如何撑开页面_寻根问底之——元素隐藏你知多少?
  3. (软件工程复习核心重点)第六章实现和测试-第八节:调试
  4. (软件工程复习核心重点)第四章总体设计-第三节:启发规则
  5. (计算机组成原理)第五章中央处理器-第三节1:CPU内部单总线数据通路中数据的流动
  6. 基础编程题之牛客网星际密码
  7. 回溯算法之全排列问题
  8. 6-5-3:STL之stack和queue——优先级队列-priority_queue(堆)的基本使用和模拟实现以及仿函数
  9. ERROR: Failed building wheel for pycrypto
  10. Python爬虫之pyppeteer的使用(爬虫、获取cookie、截屏插件、防爬绕过)