`

enum再谈

 
阅读更多

java中枚举声明需用到enum关键字简单的如:

public enum TestEnum {
	Mon,
	Tue,
	Wen,
	Fri
}

 但是我们查看一下编译后得到的汇编就能知道,enum编译后得到的还是一个class,现在用javap -verbose TestEnum命令查看编译得到的class文件:

Classfile /F:/TestEnum.class
  Last modified 2017-5-8; size 868 bytes
  MD5 checksum 485a9071bf44ca9406beceea0dbca950
  Compiled from "TestEnum.java"
public final class TestEnum extends java.lang.Enum<TestEnum>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
Constant pool:
   #1 = Fieldref           #4.#38         // TestEnum.$VALUES:[LTestEnum;
   #2 = Methodref          #39.#40        // "[LTestEnum;".clone:()Ljava/lang/Object;
   #3 = Class              #23            // "[LTestEnum;"
   #4 = Class              #41            // TestEnum
   #5 = Methodref          #16.#42        // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
   #6 = Methodref          #16.#43        // java/lang/Enum."<init>":(Ljava/lang/String;I)V
   #7 = String             #17            // Mon
   #8 = Methodref          #4.#43         // TestEnum."<init>":(Ljava/lang/String;I)V
   #9 = Fieldref           #4.#44         // TestEnum.Mon:LTestEnum;
  #10 = String             #19            // Tue
  #11 = Fieldref           #4.#45         // TestEnum.Tue:LTestEnum;
  #12 = String             #20            // Wen
  #13 = Fieldref           #4.#46         // TestEnum.Wen:LTestEnum;
  #14 = String             #21            // Fri
  #15 = Fieldref           #4.#47         // TestEnum.Fri:LTestEnum;
  #16 = Class              #48            // java/lang/Enum
  #17 = Utf8               Mon
  #18 = Utf8               LTestEnum;
  #19 = Utf8               Tue
  #20 = Utf8               Wen
  #21 = Utf8               Fri
  #22 = Utf8               $VALUES
  #23 = Utf8               [LTestEnum;
  #24 = Utf8               values
  #25 = Utf8               ()[LTestEnum;
  #26 = Utf8               Code
  #27 = Utf8               LineNumberTable
  #28 = Utf8               valueOf
  #29 = Utf8               (Ljava/lang/String;)LTestEnum;
  #30 = Utf8               <init>
  #31 = Utf8               (Ljava/lang/String;I)V
  #32 = Utf8               Signature
  #33 = Utf8               ()V
  #34 = Utf8               <clinit>
  #35 = Utf8               Ljava/lang/Enum<LTestEnum;>;
  #36 = Utf8               SourceFile
  #37 = Utf8               TestEnum.java
  #38 = NameAndType        #22:#23        // $VALUES:[LTestEnum;
  #39 = Class              #23            // "[LTestEnum;"
  #40 = NameAndType        #49:#50        // clone:()Ljava/lang/Object;
  #41 = Utf8               TestEnum
  #42 = NameAndType        #28:#51        // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #43 = NameAndType        #30:#31        // "<init>":(Ljava/lang/String;I)V
  #44 = NameAndType        #17:#18        // Mon:LTestEnum;
  #45 = NameAndType        #19:#18        // Tue:LTestEnum;
  #46 = NameAndType        #20:#18        // Wen:LTestEnum;
  #47 = NameAndType        #21:#18        // Fri:LTestEnum;
  #48 = Utf8               java/lang/Enum
  #49 = Utf8               clone
  #50 = Utf8               ()Ljava/lang/Object;
  #51 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
{
  public static final TestEnum Mon;
    descriptor: LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final TestEnum Tue;
    descriptor: LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final TestEnum Wen;
    descriptor: LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final TestEnum Fri;
    descriptor: LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  private static final TestEnum[] $VALUES;
    descriptor: [LTestEnum;
    flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

  public static TestEnum[] values();
    descriptor: ()[LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #1                  // Field $VALUES:[LTestEnum;
         3: invokevirtual #2                  // Method "[LTestEnum;".clone:()Ljava/lang/Object;
         6: checkcast     #3                  // class "[LTestEnum;"
         9: areturn
      LineNumberTable:
        line 1: 0

  public static TestEnum valueOf(java.lang.String);
    descriptor: (Ljava/lang/String;)LTestEnum;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #4                  // class TestEnum
         2: aload_0
         3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #4                  // class TestEnum
         9: areturn
      LineNumberTable:
        line 1: 0

  private TestEnum();
    descriptor: (Ljava/lang/String;I)V
    flags: ACC_PRIVATE
    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: iload_2
         3: invokespecial #6                  // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
         6: return
      LineNumberTable:
        line 1: 0
    Signature: #33                          // ()V

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=4, locals=0, args_size=0
         0: new           #4                  // class TestEnum
         3: dup
         4: ldc           #7                  // String Mon
         6: iconst_0
         7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        10: putstatic     #9                  // Field Mon:LTestEnum;
        13: new           #4                  // class TestEnum
        16: dup
        17: ldc           #10                 // String Tue
        19: iconst_1
        20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        23: putstatic     #11                 // Field Tue:LTestEnum;
        26: new           #4                  // class TestEnum
        29: dup
        30: ldc           #12                 // String Wen
        32: iconst_2
        33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        36: putstatic     #13                 // Field Wen:LTestEnum;
        39: new           #4                  // class TestEnum
        42: dup
        43: ldc           #14                 // String Fri
        45: iconst_3
        46: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        49: putstatic     #15                 // Field Fri:LTestEnum;
        52: iconst_4
        53: anewarray     #4                  // class TestEnum
        56: dup
        57: iconst_0
        58: getstatic     #9                  // Field Mon:LTestEnum;
        61: aastore
        62: dup
        63: iconst_1
        64: getstatic     #11                 // Field Tue:LTestEnum;
        67: aastore
        68: dup
        69: iconst_2
        70: getstatic     #13                 // Field Wen:LTestEnum;
        73: aastore
        74: dup
        75: iconst_3
        76: getstatic     #15                 // Field Fri:LTestEnum;
        79: aastore
        80: putstatic     #1                  // Field $VALUES:[LTestEnum;
        83: return
      LineNumberTable:
        line 2: 0
        line 3: 13
        line 4: 26
        line 5: 39
        line 1: 52
}
Signature: #35                          // Ljava/lang/Enum<LTestEnum;>;
SourceFile: "TestEnum.java"

 现在一点一点解释

1.enum最终编译得到一个继承java.lang.Enum的final class(Enum的源码这里不做讲解,很简单)

2.这个类TestEnum类,有几个类型为自身的静态最终变量Mon、Tue、Wen、Fri也就是在enum中的几个声明,以及一个TestEnum[]数组变量$VALUES

3.静态方法values(),作用是返回该类的静态变量数组$VALUES

4.静态方法valueOf(),内部调用Enum类的方法

 public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
//enumConstantDirectory返回一个第一次使用时懒加载的,简单名称与Enum实例 键值对的map
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }

 

5.私有构造方法private TestEnum();内部就是调用enum的protected构造方法

6.静态代码块,它的作用是以枚举各个元素对应的String值和从0开始的int值为参数,依次初始化TestEnum对象并赋值给对应的静态最终变量(int值跟enum的ordinal相对应,String值跟enum的name相对应),接下来就是把这些静态变量值放到$VALUES数组中

 

所有枚举就是含有自身静态变量实例的类

分享到:
评论

相关推荐

    浅谈Python 的枚举 Enum

    from enum import Enum Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) 枚举的定义 首先,定义枚举要导入enum模块。 枚举定义用class关键字,继承...

    浅谈Java中是否直接可以使用enum进行传输

    Java 中使用 enum 进行传输的可行性分析 在 Java 中,使用枚举类型(enum)来表示状态或状态值是一种非常常见的做法。但是,在将枚举类型用于传输时,需要注意一些问题。在本文中,我们将探讨 Java 中是否可以直接...

    再谈在Java中使用枚举.pdf

    public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; } ``` 现在,Java的枚举完全支持类型安全、紧凑定义、无缝交互和高效运行。你可以直接在switch语句中使用枚举,如: ```...

    深入浅出谈java修饰符共6页.pdf.zip

    然而,提供的压缩包文件"深入浅出谈java修饰符共6页.pdf.zip"似乎包含的是一个PDF文档,若要获取更多具体信息,需要解压并查看文档内容。在"赚钱项目"这个子文件中,可能涉及的是如何利用Java编程技能进行项目开发以...

    C#枚举中的位运算权限分配浅谈

    第一步, 先建立一个枚举表示所有的权限管理操作: 代码如下:[Flags] public enum Permissions { Insert = 1, Delete = 2, Update = 4, Query = 8 } [Flags]表示该枚举可以支持C#位运算, 而枚举的每一项值, 我们用2的n...

    浅谈Java泛型让声明方法返回子类型的方法

    这在自引用类型中非常常见,例如Java的`Enum`类,所有枚举类型都隐式地继承了`Enum`,并且它们的类型参数是它们自己,如`public class StatusCode extends Enum&lt;StatusCode&gt;`。 `Enum`类的声明之所以如此设计,是...

    浅谈西门子Prodave6.0在C#中的应用

    public enum PLCBlockType { I = 1, // Input bytes Q = 2, // Output bytes M = 3, // Flag bytes T = 4, // Timer words Z = 5, // Counter words D = 6, // Data from DB } ``` 此枚举定义了PLC中不同的...

    从单例谈double-check必要性,多种单例各取所需.doc

    public enum SingleFactory { INSTANCE; public Person getInstance() { return new Person(); } } ``` 总结来说,选择哪种单例模式取决于项目的需求,如是否需要延迟初始化、是否考虑线程安全、以及性能和...

    C#面向对象设计模式纵横谈(14):Chain of Responsibility 职责链模式(行为型模式) (Level 300)

    public enum RequestType { Type1, Type2 } ``` 4. 客户端代码:创建处理者链,并发起请求。 ```csharp public static void Main() { Handler handler1 = new ConcreteHandler1(); Handler handler2 = new ...

    浅谈Java枚举的作用与好处

    Java枚举(Enum)在编程中扮演着重要的角色,它是一种特殊的类,允许开发者定义一组预定义的常量。在Java中,枚举是通过关键字`enum`来创建的,它提供了一种更加安全和优雅的方式来处理有限的、固定的选项集合。本文...

    浅谈MySQL大表优化方案

    背景 阿里云RDS FOR MySQL(MySQL5.7版本)数据库业务表每月新增数据量超过千万,随着数据量持续增加,我们业务出现大表慢查询,在业务... 使用TINYINT类型代替枚举ENUM 存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBL

    浅谈JAVASE单例设计模式

    enum Singleton5 { INSTANCE; public void whateverMethod() { //... } } ``` 6. **登记式单例** 登记式单例常用于框架中,如Spring。它将所有单例对象存储在一个Map中,通过类名作为键,实例作为值。当...

    浅谈C语言编程中的布尔bool数据类型

    在C99之前,程序员通常会自定义布尔类型,常见的做法是使用`typedef`关键字和枚举(`enum`)或者宏定义(`#define`)来实现。例如: ```c typedef int BOOL; #define TRUE 1 #define FALSE 0 ``` C99标准引入了一...

    浅谈Java编程中的单例设计模式

    public enum LogUtil { INSTANCE; // ... public void debug(String msg) { // ... } // ... } ``` 在上述代码中,你可能已经注意到,原始的单例实现没有考虑到多线程环境下的线程安全问题。在Java中,如果不...

    0.2 MySQL表操作及数据类型

    除了基础类型外,MySQL还提供了复合数据类型,如ENUM(枚举)和SET(集合),它们允许从预定义的值中选择。 日期类型是数据库中另一重要的数据类型,常用的包括DATE、TIME、DATETIME和TIMESTAMP。DATE类型适合存储...

    c#获取打印机当前打印状态完整源码

    enum PrinterStatus { Offline = 1, PendingDeletion = 2, Paused = 4, PaperJam = 16, OutOfPaper = 29, NoToner = 34, // 其他状态... } ManagementObject printerObject = ... // 获取到特定打印机的对象...

    Visual Basic 2008程序设计完全自学教程 2/2

    4.7 自定义类型Structure与Enum 4.8 表达式与运算符 4.8.1 算术运算符 4.8.2 赋值运算符 4.8.3 比较运算符 4.8.4 连接运算符 4.8.5 逻辑运算符 4.8.6 运算符优先级 本章重点整理 本章习题 第5章 窗体程序基础认识 ...

Global site tag (gtag.js) - Google Analytics