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

语法糖(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 中仅存在一个常量实例,所以我们可以放心的使用“ ==”来比较两个变量。

注意事项:

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

枚举变量最好大写,多个单词之间使用”_”隔开(比如: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 类型,并在静态代码块中被初始化。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgwxw.html