前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JDK枚举原理解析

JDK枚举原理解析

作者头像
孟君
发布2019-08-28 15:13:02
5350
发布2019-08-28 15:13:02
举报

枚举是我们在编码过程中常用的,比如电影有多种类型:喜剧片、动作片、恐怖片、爱情片、纪录片等等。在这种场景当中,我们可以编写一个枚举类(如MovieType)来进行表示。

本文借助MovieType这个枚举类,通过查看编译后的内容,来简单探究一下JDK枚举类的基本原理。主要包含如下几个部分:

  1. 通过javap命令观察编译后的内容是什么?(不包含abstract方法)
  2. 通过javap命令观察编译后的内容是什么?(包含abstract方法)
  3. 小结

一、枚举编译之后是什么样子的?(无abstract方法)

编写一个名字为MovieType的枚举类,如:

代码语言:javascript
复制
package com.wangmengjun.tutorial.enums;

public enum MovieType {
  
  ACTION(1,"动作片"),COMODY(2,"喜剧片");
  
  private Integer code;
  
  private String type;

  private MovieType(Integer code, String type) {
    this.code = code;
    this.type = type;
  }

  /**
   * @return the code
   */
  public Integer getCode() {
    return code;
  }

  /**
   * @return the type
   */
  public String getType() {
    return type;
  }

}

使用javap -c -v MovieType.class,查看编译后的内容:

代码语言:javascript
复制
  Last modified 2019年8月26日; size 1575 bytes
  MD5 checksum 0f92ec5e47d72e1da315271952535909
  Compiled from "MovieType.java"
public final class com.wangmengjun.tutorial.enums.MovieType extends java.lang.Enum<com.wangmengjun.tutorial.enums.MovieType>
  minor version: 0
  major version: 49
  flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
  this_class: #1                          // com/wangmengjun/tutorial/enums/MovieType
  super_class: #3                         // java/lang/Enum
  interfaces: 0, fields: 5, methods: 6, attributes: 2
Constant pool:
   #1 = Class              #2             // com/wangmengjun/tutorial/enums/MovieType
   #2 = Utf8               com/wangmengjun/tutorial/enums/MovieType
   #3 = Class              #4             // java/lang/Enum
   #4 = Utf8               java/lang/Enum
   #5 = Utf8               ACTION
   #6 = Utf8               Lcom/wangmengjun/tutorial/enums/MovieType;
   #7 = Utf8               COMODY
   #8 = Utf8               code
   #9 = Utf8               Ljava/lang/Integer;
  #10 = Utf8               type
  #11 = Utf8               Ljava/lang/String;
  #12 = Utf8               ENUM$VALUES
  #13 = Utf8               [Lcom/wangmengjun/tutorial/enums/MovieType;
  #14 = Utf8               <clinit>
  #15 = Utf8               ()V
  #16 = Utf8               Code
  #17 = String             #5             // ACTION
  #18 = Methodref          #19.#21        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
  #19 = Class              #20            // java/lang/Integer
  #20 = Utf8               java/lang/Integer
  #21 = NameAndType        #22:#23        // valueOf:(I)Ljava/lang/Integer;
  #22 = Utf8               valueOf
  #23 = Utf8               (I)Ljava/lang/Integer;
  #24 = String             #25            // 动作片
  #25 = Utf8               动作片
  #26 = Methodref          #1.#27         // com/wangmengjun/tutorial/enums/MovieType."<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
  #27 = NameAndType        #28:#29        // "<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
  #28 = Utf8               <init>
  #29 = Utf8               (Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
  #30 = Fieldref           #1.#31         // com/wangmengjun/tutorial/enums/MovieType.ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
  #31 = NameAndType        #5:#6          // ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
  #32 = String             #7             // COMODY
  #33 = String             #34            // 喜剧片
  #34 = Utf8               喜剧片
  #35 = Fieldref           #1.#36         // com/wangmengjun/tutorial/enums/MovieType.COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
  #36 = NameAndType        #7:#6          // COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
  #37 = Fieldref           #1.#38         // com/wangmengjun/tutorial/enums/MovieType.ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
  #38 = NameAndType        #12:#13        // ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
  #39 = Utf8               LineNumberTable
  #40 = Utf8               LocalVariableTable
  #41 = Methodref          #3.#42         // java/lang/Enum."<init>":(Ljava/lang/String;I)V
  #42 = NameAndType        #28:#43        // "<init>":(Ljava/lang/String;I)V
  #43 = Utf8               (Ljava/lang/String;I)V
  #44 = Fieldref           #1.#45         // com/wangmengjun/tutorial/enums/MovieType.code:Ljava/lang/Integer;
  #45 = NameAndType        #8:#9          // code:Ljava/lang/Integer;
  #46 = Fieldref           #1.#47         // com/wangmengjun/tutorial/enums/MovieType.type:Ljava/lang/String;
  #47 = NameAndType        #10:#11        // type:Ljava/lang/String;
  #48 = Utf8               this
  #49 = Utf8               getCode
  #50 = Utf8               ()Ljava/lang/Integer;
  #51 = Utf8               getType
  #52 = Utf8               ()Ljava/lang/String;
  #53 = Utf8               values
  #54 = Utf8               ()[Lcom/wangmengjun/tutorial/enums/MovieType;
  #55 = Methodref          #56.#58        // java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
  #56 = Class              #57            // java/lang/System
  #57 = Utf8               java/lang/System
  #58 = NameAndType        #59:#60        // arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
  #59 = Utf8               arraycopy
  #60 = Utf8               (Ljava/lang/Object;ILjava/lang/Object;II)V
  #61 = Utf8               (Ljava/lang/String;)Lcom/wangmengjun/tutorial/enums/MovieType;
  #62 = Methodref          #3.#63         // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #63 = NameAndType        #22:#64        // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #64 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #65 = Utf8               SourceFile
  #66 = Utf8               MovieType.java
  #67 = Utf8               Signature
  #68 = Utf8               Ljava/lang/Enum<Lcom/wangmengjun/tutorial/enums/MovieType;>;
{
  public static final com.wangmengjun.tutorial.enums.MovieType ACTION;
    descriptor: Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final com.wangmengjun.tutorial.enums.MovieType COMODY;
    descriptor: Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=6, locals=0, args_size=0
         0: new           #1                  // class com/wangmengjun/tutorial/enums/MovieType
         3: dup
         4: ldc           #17                 // String ACTION
         6: iconst_0
         7: iconst_1
         8: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        11: ldc           #24                 // String 动作片
        13: invokespecial #26                 // Method "<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
        16: putstatic     #30                 // Field ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
        19: new           #1                  // class com/wangmengjun/tutorial/enums/MovieType
        22: dup
        23: ldc           #32                 // String COMODY
        25: iconst_1
        26: iconst_2
        27: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        30: ldc           #33                 // String 喜剧片
        32: invokespecial #26                 // Method "<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
        35: putstatic     #35                 // Field COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
        38: iconst_2
        39: anewarray     #1                  // class com/wangmengjun/tutorial/enums/MovieType
        42: dup
        43: iconst_0
        44: getstatic     #30                 // Field ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
        47: aastore
        48: dup
        49: iconst_1
        50: getstatic     #35                 // Field COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
        53: aastore
        54: putstatic     #37                 // Field ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
        57: return
      LineNumberTable:
        line 5: 0
        line 3: 38
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

  public java.lang.Integer getCode();
    descriptor: ()Ljava/lang/Integer;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #44                 // Field code:Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 20: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/wangmengjun/tutorial/enums/MovieType;

  public java.lang.String getType();
    descriptor: ()Ljava/lang/String;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #46                 // Field type:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 27: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/wangmengjun/tutorial/enums/MovieType;

  public static com.wangmengjun.tutorial.enums.MovieType[] values();
    descriptor: ()[Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=3, args_size=0
         0: getstatic     #37                 // Field ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
         3: dup
         4: astore_0
         5: iconst_0
         6: aload_0
         7: arraylength
         8: dup
         9: istore_1
        10: anewarray     #1                  // class com/wangmengjun/tutorial/enums/MovieType
        13: dup
        14: astore_2
        15: iconst_0
        16: iload_1
        17: invokestatic  #55                 // 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 com.wangmengjun.tutorial.enums.MovieType valueOf(java.lang.String);
    descriptor: (Ljava/lang/String;)Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #1                  // class com/wangmengjun/tutorial/enums/MovieType
         2: aload_0
         3: invokestatic  #62                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #1                  // class com/wangmengjun/tutorial/enums/MovieType
         9: areturn
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}
SourceFile: "MovieType.java"
Signature: #68                          // Ljava/lang/Enum<Lcom/wangmengjun/tutorial/enums/MovieType;>;

从上述字节码信息可以看出如下几点内容:

  • MovieType其实是一个final修饰的类,其继承java.lang.Enum,其泛型类型就是MovieType
代码语言:javascript
复制
public final class com.wangmengjun.tutorial.enums.MovieType 
    extends java.lang.Enum<com.wangmengjun.tutorial.enums.MovieType>
  • MovieType中定义的ACTION和COMODY变成了2个pubic static final修饰的变量,另外还有一个private static final的ENUM$VALUES变量
代码语言:javascript
复制
public static final com.wangmengjun.tutorial.enums.MovieType ACTION;
    descriptor: Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final com.wangmengjun.tutorial.enums.MovieType COMODY;
    descriptor: Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
    
  #35 = Fieldref           #1.#36         // com/wangmengjun/tutorial/enums/MovieType.COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
  #36 = NameAndType        #7:#6          // COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
  #37 = Fieldref           #1.#38         // com/wangmengjun/tutorial/enums/MovieType.ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
  #38 = NameAndType        #12:#13        // ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
  #39 = Utf8               LineNumberTable

等价于

代码语言:javascript
复制
  public static final MovieType ACTION;
  public static final MovieType COMODY;
  private static final MovieType ENUM$VALUES[];
  • ACTION、COMODY和ENUM$VALUES变量通过静态代码块初始化
代码语言:javascript
复制
static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=6, locals=0, args_size=0
         0: new           #1                  // class com/wangmengjun/tutorial/enums/MovieType
         3: dup
         4: ldc           #17                 // String ACTION
         6: iconst_0
         7: iconst_1
         8: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        11: ldc           #24                 // String 动作片
        13: invokespecial #26                 // Method "<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
        16: putstatic     #30                 // Field ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
        19: new           #1                  // class com/wangmengjun/tutorial/enums/MovieType
        22: dup
        23: ldc           #32                 // String COMODY
        25: iconst_1
        26: iconst_2
        27: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        30: ldc           #33                 // String 喜剧片
        32: invokespecial #26                 // Method "<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)V
        35: putstatic     #35                 // Field COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
        38: iconst_2
        39: anewarray     #1                  // class com/wangmengjun/tutorial/enums/MovieType
        42: dup
        43: iconst_0
        44: getstatic     #30                 // Field ACTION:Lcom/wangmengjun/tutorial/enums/MovieType;
        47: aastore
        48: dup
        49: iconst_1
        50: getstatic     #35                 // Field COMODY:Lcom/wangmengjun/tutorial/enums/MovieType;
        53: aastore
        54: putstatic     #37                 // Field ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
        57: return
      LineNumberTable:
        line 5: 0
        line 3: 38
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

等价于:

代码语言:javascript
复制
  static 
  {
    ACTION = new MovieType("ACTION", 0, Integer.valueOf(1), "动作片");
    COMODY = new MovieType("COMODY", 1, Integer.valueOf(2), "喜剧片");
    ENUM$VALUES = (new MovieType[] {
      ACTION, COMODY
    });
  }
  • 增加了values方法, public static修饰,返回类型为数据MovieType[]
代码语言:javascript
复制
public static com.wangmengjun.tutorial.enums.MovieType[] values();
    descriptor: ()[Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=3, args_size=0
         0: getstatic     #37                 // Field ENUM$VALUES:[Lcom/wangmengjun/tutorial/enums/MovieType;
         3: dup
         4: astore_0
         5: iconst_0
         6: aload_0
         7: arraylength
         8: dup
         9: istore_1
        10: anewarray     #1                  // class com/wangmengjun/tutorial/enums/MovieType
        13: dup
        14: astore_2
        15: iconst_0
        16: iload_1
        17: invokestatic  #55                 // 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

通过System.arraycopy方法来实现

  • 增加了valueof方法,public static 修饰
代码语言:javascript
复制
public static com.wangmengjun.tutorial.enums.MovieType valueOf(java.lang.String);
    descriptor: (Ljava/lang/String;)Lcom/wangmengjun/tutorial/enums/MovieType;
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #1                  // class com/wangmengjun/tutorial/enums/MovieType
         2: aload_0
         3: invokestatic  #62                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #1                  // class com/wangmengjun/tutorial/enums/MovieType
         9: areturn
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

等价于:

代码语言:javascript
复制
  public static MovieType valueOf(String s)
  {
    return (MovieType)Enum.valueOf(com/wangmengjun/tutorial/enums/MovieType, s);
  }

其是通过调用Enum的valueOf方法实现的。可以简单测试一下:

代码语言:javascript
复制
public class EnumMain {
  
  public static void main(String[] args) {
    MovieType comodyType = MovieType.valueOf(MovieType.COMODY.name());
    System.out.println(comodyType.getCode() +":" + comodyType.getType());
  }

}

debug一下,可以看到调用到Enum.valueof方法:

直观点,可以通过反编译工具,查看class文件如下:

代码语言:javascript
复制
public final class com.wangmengjun.tutorial.enums.MovieType 
    extends java.lang.Enum<com.wangmengjun.tutorial.enums.MovieType>
{

  public static final MovieType ACTION;
  public static final MovieType COMODY;
  private Integer code;
  private String type;
  private static final MovieType ENUM$VALUES[];

  private MovieType(String s, int i, Integer code, String type)
{
    super(s, i);
    this.code = code;
    this.type = type;
  }

  public Integer getCode()
{
    return code;
  }

  public String getType()
{
    return type;
  }

  public static MovieType[] values()
  {
    MovieType amovietype[];
    int i;
    MovieType amovietype1[];
    System.arraycopy(amovietype = ENUM$VALUES, 0, amovietype1 = new MovieType[i = amovietype.length], 0, i);
    return amovietype1;
  }

  public static MovieType valueOf(String s)
{
    return (MovieType)Enum.valueOf(com/wangmengjun/tutorial/enums/MovieType, s);
  }

  static 
  {
    ACTION = new MovieType("ACTION", 0, Integer.valueOf(1), "动作片");
    COMODY = new MovieType("COMODY", 1, Integer.valueOf(2), "喜剧片");
    ENUM$VALUES = (new MovieType[] {
      ACTION, COMODY
    });
  }
}

通过上述的描述,相信大家对无abstract的枚举,编译后是什么样子的?已经有了一个了解。

我们知道枚举类是可以包含抽象方法的,我们看看有什么不一样的底层实现吧。

二、枚举编译之后是什么样子的?(有abstract方法)

修改一下电影类型MovieType,增加一个descSomething的抽象方法,如下代码所示:

代码语言:javascript
复制
package com.wangmengjun.tutorial.enums;

public enum MovieType {
  
  ACTION(1,"动作片"){

    @Override
    String descSomething() {
      return "action description";
    }
    
  },COMODY(2,"喜剧片") {
    @Override
    String descSomething() {
      return "comody description";
    }
  };
  
  private Integer code;
  
  private String type;

  private MovieType(Integer code, String type) {
    this.code = code;
    this.type = type;
  }

  /**
   * @return the code
   */
  public Integer getCode() {
    return code;
  }

  /**
   * @return the type
   */
  public String getType() {
    return type;
  }

  abstract String descSomething();
}

查看class目录,我们可以发现多了2个内部类,MovieType$1.class和MovieType$2.class,分别代码枚举类定义ACTION和COMODY。

因为和第一部分的步骤类似,有兴趣的读者可以使用javap来查看字节码内容。本文直接通过反编译工具查看上述3个class的内容。

代码语言:javascript
复制
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   MovieType.java

package com.wangmengjun.tutorial.enums;


public abstract class MovieType extends Enum
{

  public static final MovieType ACTION;
  public static final MovieType COMODY;
  private Integer code;
  private String type;
  private static final MovieType ENUM$VALUES[];

  private MovieType(String s, int i, Integer code, String type)
{
    super(s, i);
    this.code = code;
    this.type = type;
  }

  public Integer getCode()
{
    return code;
  }

  public String getType()
{
    return type;
  }

  abstract String descSomething();

  public static MovieType[] values()
  {
    MovieType amovietype[];
    int i;
    MovieType amovietype1[];
    System.arraycopy(amovietype = ENUM$VALUES, 0, amovietype1 = new MovieType[i = amovietype.length], 0, i);
    return amovietype1;
  }

  public static MovieType valueOf(String s)
{
    return (MovieType)Enum.valueOf(com/wangmengjun/tutorial/enums/MovieType, s);
  }

  MovieType(String s, int i, Integer integer, String s1, MovieType movietype)
  {
    this(s, i, integer, s1);
  }

  static 
  {
    ACTION = new MovieType("ACTION", 0, Integer.valueOf(1), "动作片") {

      String descSomething()
{
        return "action description";
      }

    };
    COMODY = new MovieType("COMODY", 1, Integer.valueOf(2), "喜剧片") {

      String descSomething()
{
        return "comody description";
      }

    };
    ENUM$VALUES = (new MovieType[] {
      ACTION, COMODY
    });
  }
}
代码语言:javascript
复制

package com.wangmengjun.tutorial.enums;


// Referenced classes of package com.wangmengjun.tutorial.enums:
//      MovieType

class MovieType$1 extends MovieType
{

  String descSomething()
  {
    return "action description";
  }

  MovieType$1(String s, int i, Integer $anonymous0, String $anonymous1)
  {
    super(s, i, $anonymous0, $anonymous1, null);
  }
}
代码语言:javascript
复制
package com.wangmengjun.tutorial.enums;


// Referenced classes of package com.wangmengjun.tutorial.enums:
//      MovieType

class MovieType$2 extends MovieType
{

  String descSomething()
  {
    return "comody description";
  }

  MovieType$2(String s, int i, Integer $anonymous0, String $anonymous1)
  {
    super(s, i, $anonymous0, $anonymous1, null);
  }
}

从上述反编译后的代码可以看出,增加了abstract方法之后,与无abstract的枚举,发生了如下几个变化:

  1. 带抽象方法的枚举在经过编译器编译过后,变成了一个抽象类
  2. 枚举中定义的枚举常量,采用内部类来完成。

三、小结

通过上述两个部分的介绍,我们可以看出枚举本质上是通过普通的类来实现的,只是编译器为我们进行了处理。主要有如下几个特点:

  • 每个枚举都继承于java.lang.Enum,其泛型类型是枚举类型。
    • 如果无abstract方法,其类是final修饰的
    • 如果有abstract方法,其类是abstract修饰的
  • 枚举定义的元素变成pubic static final修饰的变量,采用静态代码块的方式进行初始化
    • 如有abstract方法,其会为每个定义的元素生成一个内部类
  • 增加了values方法,用于返回枚举常量数组,内部采用System.arraycopy实现
  • 增加了valueof方法,其采用Enum的valueof方法实现
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档