JDK枚举原理解析

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

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

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

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

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

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,查看编译后的内容:

  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
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变量
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

等价于

  public static final MovieType ACTION;
  public static final MovieType COMODY;
  private static final MovieType ENUM$VALUES[];
  • ACTION、COMODY和ENUM$VALUES变量通过静态代码块初始化
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

等价于:

  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[]
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 修饰
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

等价于:

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

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

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文件如下:

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的抽象方法,如下代码所示:

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的内容。

// 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
    });
  }
}
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);
  }
}
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方法实现

本文分享自微信公众号 - 孟君的编程札记(gh_0f0f5e0ae1de),作者:孟君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 命令模式浅析

    说起命令模式,第一个引入脑海的是Java的GUI图形化编程,其中就采用了命令模式处理事件。在这个事件处理模型里面,命令对象实现AWT的Listener接口,相当...

    孟君
  • JDK注解原理探索

    在平时项目开发中,注解Annotation是我们常常用到的。比如使用Spring,其中@Autowired、@Component、@Service、@Resou...

    孟君
  • LinkedList的实现原理浅析

    查看LinkedList的源码,发现其继承自AbstractSequentialList,实现了List,Deque,Cloneable以及Serializab...

    孟君
  • 哪里的云服务好,选择腾讯云的理由

    现在的云服务器种类众多,配置参数项目也比较多。新用户在选择云服务器哪家好时,会想着云服务器哪家好?对于要购买云服务器的用户来说,面对众多的商家品牌,很难确定到底...

    tengxunyun8点com活动整理
  • SAP 采购申请介绍

    SAP采购申请是为物料采购活动的中间部分。SAP系统经过MRP运算产生对物料的采购申请或者在SAP系统中手工创建采购申请,通过对采购申请的管理可以实现对需求来源...

    用户5495712
  • vue项目前端规范

    // 数组解构赋值 const arr = [1, 2, 3, 4] // bad const first = arr[0] const second = a...

    薛定喵君
  • PipeHttp 测试工具使用

    https://github.com/lulianqi/PipeHttp/ (工程地址)

    lulianqi
  • 2020年如何写一个现代的JavaScript库

    我写过一些开源项目,在开源方面有一些经验,最近开到了阮老师的微博,深有感触,现在一个开源项目涉及的东西确实挺多的,特别是对于新手来说非常不友好

    Fundebug
  • 关于Rollup那些事

    下一代打包工具,这是rollup对自己的定位。如今的前端领域,构建工具并不缺少,每个前端工程师都用过或者听过webpack。可以看到的是像React、Vue等框...

    腾讯IVWEB团队
  • 7-4 括号匹配 (25 分)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    韩旭051

扫码关注云+社区

领取腾讯云代金券