博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
枚举原理与常见用法与技巧
阅读量:6735 次
发布时间:2019-06-25

本文共 29653 字,大约阅读时间需要 98 分钟。

hot3.png

枚举简介

首先是代替使用常量枚举方式,这种方式是最常用的的方式。 假设我们有一个payStatus,不同值分别代表的含义如下: 0-初始化,1-支付中,2-支付成功,3-支付失败。 我们先来看一个直接用连int型枚举常量都难得提供的方式:

public class Pay {        private int payStatus;            public int getPayStatus() {        return payStatus;    }    public void setPayStatus(int payStatus) {        this.payStatus = payStatus;    }    public static void main(String[] args) {//        0-初始化,1-支付中,2-支付成功,3-支付失败        Pay pay = new Pay();        pay.setPayStatus(4);        switch(pay.getPayStatus()){        case 0:             System.out.println("初始化");            break;        case 1:             System.out.println("支付中");            break;        case 2:             System.out.println("支付成功");            break;        case 3:             System.out.println("支付失败");            break;        default:            throw new IllegalStateException("错误的支付状态");        }    }}

像上面的代码,对于使用者来说是非常不友好的,鬼知道0,1,2,3代表的是什么,猜测都不好猜,并且不好记忆,最严重的是没有限制。像上面完全可以把payStatus设置为4。

下面来一个提供int型枚举的方式:

public class Pay {        /**     * 支付初始化     */    public static final int INIT = 0;        /**     * 支付中     */    public static final int PAYING = 1;        /**     * 支付成功     */    public static final int SUCCESS = 2;        /**     * 支付失败     */    public static final int FAIL = 3;        private int payStatus;            public int getPayStatus() {        return payStatus;    }    public void setPayStatus(int payStatus) {        this.payStatus = payStatus;    }    public static void main(String[] args) {//        0-初始化,1-支付中,2-支付成功,3-支付失败        Pay pay = new Pay();        pay.setPayStatus(PAYING);        switch(pay.getPayStatus()){        case 0:             System.out.println("初始化");            break;        case 1:             System.out.println("支付中");            break;        case 2:             System.out.println("支付成功");            break;        case 3:             System.out.println("支付失败");            break;        default:            throw new IllegalStateException("错误的支付状态");        }    }}

这种方式就常见的多了,我们在很多第三方库中都能看到这样的方式。这样对于习惯这样的模式的开发者就比较方便了,也方便记忆和使用。但是同样没有做限制。pay.setPayStatus(4);这样的调用方式,使得在运行时才抛出异常。

接下来我们看使用枚举的模式: 枚举类型:

public enum PayStatus {    INIT(0,"初始化"),    PAYING(1,"支付中"),    SUCCESS(2,"支付成功"),    FAIL(3,"支付失败");    private Integer id;    private String desc;        private static final Map
idToEnum = new HashMap
(); static { for (PayStatus op : values()) idToEnum.put(op.id, op); } public static PayStatus getInstance(Integer id) { return idToEnum.get(id); } private PayStatus(Integer id, String desc){ this.id = id; this.desc = desc; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return desc; }}

对于枚举类型,最后使用实例域,不要使用枚举的默认序数ordinal,因为添加和交互顺序都可能改变ordinal,这样对于依赖以ordinal的客户端都会出错。所以添加实例域id来表示。 这里有2个小技巧:

  1. 缓存id与枚举的对应关系,并提供静态公有方法,因为很多时候需要通过id值获取枚举,比如说在数据库中存放枚举使用的是整形的id值,ORM时候需要转换int为枚举类型
  2. 重写toString,很多时候展示层希望显示的是desc描述字段,重写了toString就可以直接通过打印枚举类型就可以打印desc的字段的类容。
public class Pay {        private PayStatus payStatus;        public PayStatus getPayStatus() {        return payStatus;    }    public void setPayStatus(PayStatus payStatus) {        this.payStatus = payStatus;    }    public static void main(String[] args) {//        0-初始化,1-支付中,2-支付成功,3-支付失败        Pay pay = new Pay();        pay.setPayStatus(PayStatus.PAYING);        switch(pay.getPayStatus()){        case INIT:             System.out.println("初始化");            break;        case PAYING:             System.out.println("支付中");            break;        case SUCCESS:             System.out.println("支付成功");            break;        case FAIL:             System.out.println("支付失败");            break;        default:            throw new IllegalStateException("错误的支付状态");        }    }}

我们把支付状态从int类型换成了PayStatus枚举类型,就限制了客户端传递错误的状态参数,客户端也可以很容易的从枚举类型PayStatus中选择需要的状态。

枚举与行为绑定

这个属于比较少见的,但是的确非常有潜力的使用方式,下面是Effictive Java中的一个例子:

import java.util.HashMap;import java.util.Map;public enum Operation {    PLUS("+") {        double apply(double x, double y) {            return x + y;        }    },    MINUS("-") {        double apply(double x, double y) {            return x - y;        }    },    TIMES("*") {        double apply(double x, double y) {            return x * y;        }    },    DIVIDE("/") {        double apply(double x, double y) {            return x / y;        }    };    private final String symbol;    Operation(String symbol) {        this.symbol = symbol;    }    @Override    public String toString() {        return symbol;    }    abstract double apply(double x, double y);    private static final Map
stringToEnum = new HashMap
(); static { for (Operation op : values()) stringToEnum.put(op.toString(), op); } public static Operation fromString(String symbol) { return stringToEnum.get(symbol); } public static void main(String[] args) { double x = 2; double y = 4; for (Operation op : Operation.values()) System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y)); }}

这里主要主要的是这种方式,注意思考abstract double apply(double x, double y);抽象方法。

枚举原理

我们对上面的枚举类型PayStatus的class文件进行反编译(只看签名,不看字节码,只是用-private参数输出所有类和成员):

javap -private PayStatus

内容如下:

public final class cn.freemethod.type.PayStatus extends java.lang.Enum
{ public static final cn.freemethod.type.PayStatus INIT; public static final cn.freemethod.type.PayStatus PAYING; public static final cn.freemethod.type.PayStatus SUCCESS; public static final cn.freemethod.type.PayStatus FAIL; private java.lang.Integer id; private java.lang.String desc; private static final java.util.Map
idToEnum; private static final cn.freemethod.type.PayStatus[] ENUM$VALUES; static {}; public static cn.freemethod.type.PayStatus getInstance(java.lang.Integer); private cn.freemethod.type.PayStatus(java.lang.String, int, java.lang.Integer, java.lang.String); public java.lang.Integer getId(); public void setId(java.lang.Integer); public java.lang.String getDesc(); public void setDesc(java.lang.String); public java.lang.String toString(); public static cn.freemethod.type.PayStatus[] values(); public static cn.freemethod.type.PayStatus valueOf(java.lang.String);}

从上面PayStatus反编译的代码来看,Java枚举就是一个语法糖,本质上还是被编译为了class,只不过这个类继承了Enum类,并且包含了自身的引用做为枚举值。 这里并没有输出字节码,如果使用(-verbose或者-c参数):

javap -verbose PayStatus

输出字节码就会发现在static初始化阶段,通过调用valueOf(String name)这个静态方法为INIT; PAYING; SUCCESS; FAIL;这些枚举值赋值。valueOf调用了Enum的静态方法

public static 
> T valueOf(Class
enumType, String name)
public static cn.freemethod.type.PayStatus valueOf(java.lang.String);

从上面的方法反编译的字节码中我们看到了把PayStatus.class传给了Enum的valueOf。 调用的线大概就是下面的样子: PayStatus.valueOf->Enum.valueOf->Class.enumConstantDirectory->Class.getEnumConstantsShared->PayStatus.values 上面这个有一点抽象,我们来理一理。从字节码中(见附录)可以看出PayStatus枚举(enum)被编译为了类(Class),并且继承了Enum类,注意Enum是类(Class)类型,而不是枚举(enum)类型,并且把每一个枚举都编译为了一个自身类型的静态引用,并且在static中初始化的,从初始化字节码中可以看到传递了4个参数。其中2个是中enum中定义的id和desc,另外另个是编译器生成的name和ordinal。在调用PayStatus构造的时候把name和ordinal传递给了Enum构造函数。 另外,在初始化的时候,实例化了每一个枚举代表的类,并且把这些枚举代表的类的实例保存到了一个Enum数组中。

从上面的字节码签名以及分析中可以看到枚举被编译成为了,饿汉式的工厂类,有多少个枚举就初始化多少个类。然后就可以通过类或者静态工厂方法获取相应的实例。

注意:上面原理没有理清楚没有关系,但是注意下面这2条

  1. name代表的是枚举中的类型(字面量),就是被编译为类之后的自身的引用,像PayStatus中的INIT、PAYING、SUCCESS、FAIL,使用枚举的valueOf(String name)获取枚举使用的name就是这个name,枚举类的name()方法获取的值也是这个。
  2. ordinal是编译器生成的从0开始,第一个是0,第2个是1,以此类推。

EnumSet

如果一个枚举类型主要用在集合中,一般使用int枚举模式,并且将2的不同倍数赋予每一个常量。最著名的就是java.lang.reflect.Modifier类。另外一个比较经典的例子是在枚举中使用的fastjson的com.alibaba.fastjson.serializer.SerializerFeature这个类。关于SerializerFeature可以参考:

下面看一个使用EnumSet改造的SerializerFeature类:

import java.util.EnumSet;public enum SerializerFeature {    QuoteFieldNames,    /**     *      */    UseSingleQuotes,    /**     *      */    WriteMapNullValue,    /**     * 用枚举toString()值输出     */    WriteEnumUsingToString,    /**     * 用枚举name()输出     */    WriteEnumUsingName,    /**     *      */    UseISO8601DateFormat,    /**     * @since 1.1     */    WriteNullListAsEmpty,    /**     * @since 1.1     */    WriteNullStringAsEmpty,    /**     * @since 1.1     */    WriteNullNumberAsZero,    /**     * @since 1.1     */    WriteNullBooleanAsFalse,    /**     * @since 1.1     */    SkipTransientField,    /**     * @since 1.1     */    SortField,    /**     * @since 1.1.1     */    @Deprecated    WriteTabAsSpecial,    /**     * @since 1.1.2     */    PrettyFormat,    /**     * @since 1.1.2     */    WriteClassName,    /**     * @since 1.1.6     */    DisableCircularReferenceDetect,    /**     * @since 1.1.9     */    WriteSlashAsSpecial,    /**     * @since 1.1.10     */    BrowserCompatible,    /**     * @since 1.1.14     */    WriteDateUseDateFormat,    /**     * @since 1.1.15     */    NotWriteRootClassName,    /**     * @since 1.1.19     */    DisableCheckSpecialChar,    /**     * @since 1.1.35     */    BeanToArray,    /**     * @since 1.1.37     */    WriteNonStringKeyAsString,        /**     * @since 1.1.42     */    NotWriteDefaultValue,        /**     * @since 1.2.6     */    BrowserSecure,        /**     * @since 1.2.7     */    IgnoreNonFieldGetter;    public static boolean isEnabled(EnumSet
features, SerializerFeature feature) { return features.contains(feature); } public static boolean isEnabled(EnumSet
features, EnumSet
fieaturesB, SerializerFeature feature) { return features.contains(feature) || fieaturesB.contains(feature); } public static EnumSet
config(EnumSet
features, SerializerFeature feature, boolean state) { if (state) { features.add(feature); } else { features.remove(feature); } return features; } public static EnumSet
of(SerializerFeature[] features) { EnumSet
result = EnumSet.noneOf(SerializerFeature.class); if (features == null) { return result; } for (SerializerFeature feature: features) { result.add(feature); } return result; }}

上面改造的已经改变了接口,只是为了介绍EnumSet的使用。如果觉得上面的例子有一点晦涩,再看一下下面的简单的例子,假设有一个资源包,包含n中语言,怎样设计这个语言的枚举类型呢?可以参考下面的例子:

import java.util.EnumSet;public enum Language {        CHINESE,    ENGLISH,    JAPANESE,    FRENCH,    ARABIC;        /**     * languages是否包含language     * @param languages     * @param language     * @return     */    public static boolean isEnabled(EnumSet
languages, Language language) { return languages.contains(language); } /** * 检查language是否包含在languages中或者languagesB中 * @param languages * @param languagesB * @param language * @return */ public static boolean isEnabled(EnumSet
languages, EnumSet
languagesB, Language language) { return languages.contains(language) || languagesB.contains(language); } /** * 如果state为true就在languages中添加language语言 * 如果state为false就从languages中移除language语言 * @param languages * @param language * @param state * @return */ public static EnumSet
config(EnumSet
languages, Language language, boolean state) { if (state) { languages.add(language); } else { languages.remove(language); } return languages; } /** * 从languages数组中获取枚举集合 * @param languages * @return */ public static EnumSet
of(Language[] languages) { EnumSet
result = EnumSet.noneOf(Language.class); if (languages == null) { return result; } for (Language language: languages) { result.add(language); } return result; }}

当资源包包含多种语言的时候使用EnumSet就非常方便。当然如果要在数据库中存放一个整形的话,还是考虑一下使用int型来做位运算吧。

EnumMap

EnumMap从名字就知道是针对枚举的map,就是枚举到值的映射。感觉和HashMap很像,但是针对枚举做了优化,如果map的键是枚举类型,优先考虑EnumMap。 下面还是列一个Effective Java中的例子:

import java.util.EnumMap;import java.util.HashSet;import java.util.Map;import java.util.Set;public class Herb {    public enum Type {        ANNUAL, PERENNIAL, BIENNIAL    }    private final String name;    private final Type type;    Herb(String name, Type type) {        this.name = name;        this.type = type;    }    @Override    public String toString() {        return name;    }    public static void main(String[] args) {        Herb[] garden = { new Herb("Basil", Type.ANNUAL),                new Herb("Carroway", Type.BIENNIAL),                new Herb("Dill", Type.ANNUAL),                new Herb("Lavendar", Type.PERENNIAL),                new Herb("Parsley", Type.BIENNIAL),                new Herb("Rosemary", Type.PERENNIAL) };        Map
> herbsByType = new EnumMap
>(Herb.Type.class);// Map
> herbsByType = new HashMap
>(); for (Herb.Type t : Herb.Type.values()) herbsByType.put(t, new HashSet
()); for (Herb h : garden) herbsByType.get(h.type).add(h); System.out.println(herbsByType); }}

枚举的扩展

枚举是不能被继承的,从上面的分析也知道,枚举是一个语法糖被编译为了final类型的Class,所以显然是不能被继承的。但是枚举可以实现接口,虽然这种方式很少间,但是是值得思考的,可以考虑应用到策略和状态模式之中。 这个还是列一个Efficient Java中的例子来看一下:

public interface Operation {    double apply(double x, double y);}
import java.util.Arrays;import java.util.Collection;public enum ExtendedOperation implements Operation {    EXP("^") {        public double apply(double x, double y) {            return Math.pow(x, y);        }    },    REMAINDER("%") {        public double apply(double x, double y) {            return x % y;        }    };    private final String symbol;    ExtendedOperation(String symbol) {        this.symbol = symbol;    }    @Override    public String toString() {        return symbol;    }    public static void main(String[] args) {        double x = 2;        double y = 4;        test1(ExtendedOperation.class, x, y);        System.out.println();        test2(Arrays.asList(ExtendedOperation.values()), x, y);    }    /**     * T 类型必须继承之Enum,并且是Operation类型(实现Operation接口)     * @param opSet     * @param x     * @param y     */    private static 
& Operation> void test1(Class
opSet, double x, double y) { //getEnumConstants()方法是获取所有的枚举常量,就是class类型枚举类型的实例 for (Operation op : opSet.getEnumConstants()) System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y)); } private static void test2(Collection
opSet, double x, double y) { for (Operation op : opSet) System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y)); }}

总结

  1. 枚举的构造方法是私有的(或者包)
  2. 尽量不要利用枚举的序数ordinal
  3. 考虑缓存id与枚举的map
  4. 弄清楚name、ordinal和valueOf代表的含义
  5. 枚举是不能被继承的,但是可以实现接口,可以通过实现接口扩展

附录:Paystatus字节码

下面的字节码是上面的PayStatus.java编译为class后反编译得到的:

javap -s -private -verbose PayStatus

使用-s是为了输出签名(括号中是参数,后面是返回值。例如:(Ljava/lang/Integer;)Lcn/freemethod/type/PayStatus表示的是参数是一个Integer类型的类(L开头),返回值是PayStatus类),-private是为了输出所有的成员,因为枚举的构造方法是私有的。使用-verbose是为了输出字节码,也可以使用-c代替。可以使用下面的命令重定向到文件:

javap -s -private -verbose PayStatus>PayStatus.txt
MD5 checksum 052bf11bd45bc1e2d573f3cd6a179ac1  Compiled from "PayStatus.java"public final class cn.freemethod.type.PayStatus extends java.lang.Enum
SourceFile: "PayStatus.java" Signature: #111 // Ljava/lang/Enum
; minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUMConstant pool: #1 = Class #2 // cn/freemethod/type/PayStatus #2 = Utf8 cn/freemethod/type/PayStatus #3 = Class #4 // java/lang/Enum #4 = Utf8 java/lang/Enum #5 = Utf8 INIT #6 = Utf8 Lcn/freemethod/type/PayStatus; #7 = Utf8 PAYING #8 = Utf8 SUCCESS #9 = Utf8 FAIL #10 = Utf8 id #11 = Utf8 Ljava/lang/Integer; #12 = Utf8 desc #13 = Utf8 Ljava/lang/String; #14 = Utf8 idToEnum #15 = Utf8 Ljava/util/Map; #16 = Utf8 Signature #17 = Utf8 Ljava/util/Map
; #18 = Utf8 ENUM$VALUES #19 = Utf8 [Lcn/freemethod/type/PayStatus; #20 = Utf8
#21 = Utf8 ()V #22 = Utf8 Code #23 = String #5 // INIT #24 = Methodref #25.#27 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer; #25 = Class #26 // java/lang/Integer #26 = Utf8 java/lang/Integer #27 = NameAndType #28:#29 // valueOf:(I)Ljava/lang/Integer; #28 = Utf8 valueOf #29 = Utf8 (I)Ljava/lang/Integer; #30 = String #31 // 初始化 #31 = Utf8 初始化 #32 = Methodref #1.#33 // cn/freemethod/type/PayStatus."
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V #33 = NameAndType #34:#35 // "
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V #34 = Utf8
#35 = Utf8 (Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V #36 = Fieldref #1.#37 // cn/freemethod/type/PayStatus.INIT:Lcn/freemethod/type/PayStatus; #37 = NameAndType #5:#6 // INIT:Lcn/freemethod/type/PayStatus; #38 = String #7 // PAYING #39 = String #40 // 支付中 #40 = Utf8 支付中 #41 = Fieldref #1.#42 // cn/freemethod/type/PayStatus.PAYING:Lcn/freemethod/type/PayStatus; #42 = NameAndType #7:#6 // PAYING:Lcn/freemethod/type/PayStatus; #43 = String #8 // SUCCESS #44 = String #45 // 支付成功 #45 = Utf8 支付成功 #46 = Fieldref #1.#47 // cn/freemethod/type/PayStatus.SUCCESS:Lcn/freemethod/type/PayStatus; #47 = NameAndType #8:#6 // SUCCESS:Lcn/freemethod/type/PayStatus; #48 = String #9 // FAIL #49 = String #50 // 支付失败 #50 = Utf8 支付失败 #51 = Fieldref #1.#52 // cn/freemethod/type/PayStatus.FAIL:Lcn/freemethod/type/PayStatus; #52 = NameAndType #9:#6 // FAIL:Lcn/freemethod/type/PayStatus; #53 = Fieldref #1.#54 // cn/freemethod/type/PayStatus.ENUM$VALUES:[Lcn/freemethod/type/PayStatus; #54 = NameAndType #18:#19 // ENUM$VALUES:[Lcn/freemethod/type/PayStatus; #55 = Class #56 // java/util/HashMap #56 = Utf8 java/util/HashMap #57 = Methodref #55.#58 // java/util/HashMap."
":()V #58 = NameAndType #34:#21 // "
":()V #59 = Fieldref #1.#60 // cn/freemethod/type/PayStatus.idToEnum:Ljava/util/Map; #60 = NameAndType #14:#15 // idToEnum:Ljava/util/Map; #61 = Methodref #1.#62 // cn/freemethod/type/PayStatus.values:()[Lcn/freemethod/type/PayStatus; #62 = NameAndType #63:#64 // values:()[Lcn/freemethod/type/PayStatus; #63 = Utf8 values #64 = Utf8 ()[Lcn/freemethod/type/PayStatus; #65 = Fieldref #1.#66 // cn/freemethod/type/PayStatus.id:Ljava/lang/Integer; #66 = NameAndType #10:#11 // id:Ljava/lang/Integer; #67 = InterfaceMethodref #68.#70 // java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; #68 = Class #69 // java/util/Map #69 = Utf8 java/util/Map #70 = NameAndType #71:#72 // put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; #71 = Utf8 put #72 = Utf8 (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; #73 = Utf8 LineNumberTable #74 = Utf8 LocalVariableTable #75 = Utf8 op #76 = Utf8 StackMapTable #77 = Class #19 // "[Lcn/freemethod/type/PayStatus;" #78 = Utf8 getInstance #79 = Utf8 (Ljava/lang/Integer;)Lcn/freemethod/type/PayStatus; #80 = InterfaceMethodref #68.#81 // java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object; #81 = NameAndType #82:#83 // get:(Ljava/lang/Object;)Ljava/lang/Object; #82 = Utf8 get #83 = Utf8 (Ljava/lang/Object;)Ljava/lang/Object; #84 = Methodref #3.#85 // java/lang/Enum."
":(Ljava/lang/String;I)V #85 = NameAndType #34:#86 // "
":(Ljava/lang/String;I)V #86 = Utf8 (Ljava/lang/String;I)V #87 = Fieldref #1.#88 // cn/freemethod/type/PayStatus.desc:Ljava/lang/String; #88 = NameAndType #12:#13 // desc:Ljava/lang/String; #89 = Utf8 this #90 = Utf8 getId #91 = Utf8 ()Ljava/lang/Integer; #92 = Utf8 setId #93 = Utf8 (Ljava/lang/Integer;)V #94 = Utf8 getDesc #95 = Utf8 ()Ljava/lang/String; #96 = Utf8 setDesc #97 = Utf8 (Ljava/lang/String;)V #98 = Utf8 toString #99 = Methodref #100.#102 // java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V #100 = Class #101 // java/lang/System #101 = Utf8 java/lang/System #102 = NameAndType #103:#104 // arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V #103 = Utf8 arraycopy #104 = Utf8 (Ljava/lang/Object;ILjava/lang/Object;II)V #105 = Utf8 (Ljava/lang/String;)Lcn/freemethod/type/PayStatus; #106 = Methodref #3.#107 // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; #107 = NameAndType #28:#108 // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; #108 = Utf8 (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; #109 = Utf8 SourceFile #110 = Utf8 PayStatus.java #111 = Utf8 Ljava/lang/Enum
;{ public static final cn.freemethod.type.PayStatus INIT; Signature: Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM public static final cn.freemethod.type.PayStatus PAYING; Signature: Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM public static final cn.freemethod.type.PayStatus SUCCESS; Signature: Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM public static final cn.freemethod.type.PayStatus FAIL; Signature: Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM private java.lang.Integer id; Signature: Ljava/lang/Integer; flags: ACC_PRIVATE private java.lang.String desc; Signature: Ljava/lang/String; flags: ACC_PRIVATE private static final java.util.Map
idToEnum; Signature: Ljava/util/Map; flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL Signature: #17 // Ljava/util/Map
; private static final cn.freemethod.type.PayStatus[] ENUM$VALUES; Signature: [Lcn/freemethod/type/PayStatus; flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC static {}; Signature: ()V flags: ACC_STATIC Code: stack=6, locals=4, args_size=0 0: new #1 // class cn/freemethod/type/PayStatus 3: dup 4: ldc #23 // String INIT 6: iconst_0 7: iconst_0 8: invokestatic #24 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 11: ldc #30 // String 初始化 13: invokespecial #32 // Method "
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V 16: putstatic #36 // Field INIT:Lcn/freemethod/type/PayStatus; 19: new #1 // class cn/freemethod/type/PayStatus 22: dup 23: ldc #38 // String PAYING 25: iconst_1 26: iconst_1 27: invokestatic #24 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 30: ldc #39 // String 支付中 32: invokespecial #32 // Method "
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V 35: putstatic #41 // Field PAYING:Lcn/freemethod/type/PayStatus; 38: new #1 // class cn/freemethod/type/PayStatus 41: dup 42: ldc #43 // String SUCCESS 44: iconst_2 45: iconst_2 46: invokestatic #24 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 49: ldc #44 // String 支付成功 51: invokespecial #32 // Method "
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V 54: putstatic #46 // Field SUCCESS:Lcn/freemethod/type/PayStatus; 57: new #1 // class cn/freemethod/type/PayStatus 60: dup 61: ldc #48 // String FAIL 63: iconst_3 64: iconst_3 65: invokestatic #24 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 68: ldc #49 // String 支付失败 70: invokespecial #32 // Method "
":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V 73: putstatic #51 // Field FAIL:Lcn/freemethod/type/PayStatus; 76: iconst_4 77: anewarray #1 // class cn/freemethod/type/PayStatus 80: dup 81: iconst_0 82: getstatic #36 // Field INIT:Lcn/freemethod/type/PayStatus; 85: aastore 86: dup 87: iconst_1 88: getstatic #41 // Field PAYING:Lcn/freemethod/type/PayStatus; 91: aastore 92: dup 93: iconst_2 94: getstatic #46 // Field SUCCESS:Lcn/freemethod/type/PayStatus; 97: aastore 98: dup 99: iconst_3 100: getstatic #51 // Field FAIL:Lcn/freemethod/type/PayStatus; 103: aastore 104: putstatic #53 // Field ENUM$VALUES:[Lcn/freemethod/type/PayStatus; 107: new #55 // class java/util/HashMap 110: dup 111: invokespecial #57 // Method java/util/HashMap."
":()V 114: putstatic #59 // Field idToEnum:Ljava/util/Map; 117: invokestatic #61 // Method values:()[Lcn/freemethod/type/PayStatus; 120: dup 121: astore_3 122: arraylength 123: istore_2 124: iconst_0 125: istore_1 126: goto 150 129: aload_3 130: iload_1 131: aaload 132: astore_0 133: getstatic #59 // Field idToEnum:Ljava/util/Map; 136: aload_0 137: getfield #65 // Field id:Ljava/lang/Integer; 140: aload_0 141: invokeinterface #67, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 146: pop 147: iinc 1, 1 150: iload_1 151: iload_2 152: if_icmplt 129 155: return LineNumberTable: line 13: 0 line 14: 19 line 15: 38 line 16: 57 line 21: 107 line 23: 117 line 24: 133 line 23: 147 line 25: 155 LocalVariableTable: Start Length Slot Name Signature 133 14 0 op Lcn/freemethod/type/PayStatus; StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 129 locals = [ top, int, int, class "[Lcn/freemethod/type/PayStatus;" ] stack = [] frame_type = 20 /* same */ public static cn.freemethod.type.PayStatus getInstance(java.lang.Integer); Signature: (Ljava/lang/Integer;)Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #59 // Field idToEnum:Ljava/util/Map; 3: aload_0 4: invokeinterface #80, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object; 9: checkcast #1 // class cn/freemethod/type/PayStatus 12: areturn LineNumberTable: line 28: 0 LocalVariableTable: Start Length Slot Name Signature 0 13 0 id Ljava/lang/Integer; private cn.freemethod.type.PayStatus(java.lang.String, int, java.lang.Integer, java.lang.String); Signature: (Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V flags: ACC_PRIVATE Code: stack=3, locals=5, args_size=5 0: aload_0 1: aload_1 2: iload_2 3: invokespecial #84 // Method java/lang/Enum."
":(Ljava/lang/String;I)V 6: aload_0 7: aload_3 8: putfield #65 // Field id:Ljava/lang/Integer; 11: aload_0 12: aload 4 14: putfield #87 // Field desc:Ljava/lang/String; 17: return LineNumberTable: line 31: 0 line 32: 6 line 33: 11 line 34: 17 LocalVariableTable: Start Length Slot Name Signature 0 18 0 this Lcn/freemethod/type/PayStatus; 0 18 3 id Ljava/lang/Integer; 0 18 4 desc Ljava/lang/String; public java.lang.Integer getId(); Signature: ()Ljava/lang/Integer; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #65 // Field id:Ljava/lang/Integer; 4: areturn LineNumberTable: line 37: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcn/freemethod/type/PayStatus; public void setId(java.lang.Integer); Signature: (Ljava/lang/Integer;)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #65 // Field id:Ljava/lang/Integer; 5: return LineNumberTable: line 41: 0 line 42: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcn/freemethod/type/PayStatus; 0 6 1 id Ljava/lang/Integer; public java.lang.String getDesc(); Signature: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #87 // Field desc:Ljava/lang/String; 4: areturn LineNumberTable: line 45: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcn/freemethod/type/PayStatus; public void setDesc(java.lang.String); Signature: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #87 // Field desc:Ljava/lang/String; 5: return LineNumberTable: line 49: 0 line 50: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcn/freemethod/type/PayStatus; 0 6 1 desc Ljava/lang/String; public java.lang.String toString(); Signature: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #87 // Field desc:Ljava/lang/String; 4: areturn LineNumberTable: line 54: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcn/freemethod/type/PayStatus; public static cn.freemethod.type.PayStatus[] values(); Signature: ()[Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC Code: stack=5, locals=3, args_size=0 0: getstatic #53 // Field ENUM$VALUES:[Lcn/freemethod/type/PayStatus; 3: dup 4: astore_0 5: iconst_0 6: aload_0 7: arraylength 8: dup 9: istore_1 10: anewarray #1 // class cn/freemethod/type/PayStatus 13: dup 14: astore_2 15: iconst_0 16: iload_1 17: invokestatic #99 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V 20: aload_2 21: areturn LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature public static cn.freemethod.type.PayStatus valueOf(java.lang.String); Signature: (Ljava/lang/String;)Lcn/freemethod/type/PayStatus; flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: ldc #1 // class cn/freemethod/type/PayStatus 2: aload_0 3: invokestatic #106 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 6: checkcast #1 // class cn/freemethod/type/PayStatus 9: areturn LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature}

转载于:https://my.oschina.net/u/2474629/blog/840457

你可能感兴趣的文章