首页 > 其他分享 >枚举实现原理

枚举实现原理

时间:2024-08-29 21:36:19浏览次数:10  
标签:实现 object 枚举 victory test 原理 size Subject

枚举的定义

在JDK1.5之前,我们要是想定义一些有关常量的内容,例如定义几个常量,表示从周一到周末,一般都是在一个类,或者一个接口中,写类似于如下代码:

public class WeekDayConstant {
    public static final int MONDAY = 0;
    public static final int TUESDAY = 1;
    public static final int WEDNESDAY = 2;
    public static final int THURSDAY = 3;
    //...
}

这样做也可以实现功能,有几个缺点:

  • 各个常量的值可能会一样,出现混淆,例如不小心把TUESDAY 定义为0
  • 使用起来并不是很方便,例如想要获取某一种枚举的所有枚举值列表,根名称获取值等,还要去编码实现
  • 并不是很安全,例如反射修改常量的值,MONDAY 的值可能被修改为1
  • 方式并不是很优雅

为了不重复造轮子,Java在JDK1.5的时候,引入了枚举enum关键字(enum就是enumeration的缩写),我们可以定义枚举类型。

访问修饰符 enum 枚举类型名称{
	//一个或多个枚举值定义,一般采用大写加下划线的方式,用英文逗号分隔,例如,
	A,B,C;
	//在最后一个枚举值后面建议加一个分号,对于与只有枚举值的枚举定义来说,可以没有分号
	//后面就是一些方法的定义
}

例如,周一到周末的枚举定义:

public enum WeekDay {
    MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}

可以单独定义一个文件,也可以定义在其他类的文件中。

枚举的实现原理

先从简单的来,我现在把我们上面使用的Subject枚举类改成下面的样子:

public enum Subject {
    CHINESE,
    MATH,
    ENGLISH;
}

切换到class所在的目录,然后:

javap -c Subject.class

javap是JDK自带的反汇编工具,得到下面的结果:

Compiled from "Subject.java"
public final class com.victory.test.object_size.Subject extends java.lang.Enum<com.victory.test.object_size.Subject> {
  public static final com.victory.test.object_size.Subject CHINESE;

  public static final com.victory.test.object_size.Subject MATH;

  public static final com.victory.test.object_size.Subject ENGLISH;

  public static com.victory.test.object_size.Subject[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Lcom/victory/test/object_size/Subject;
       3: invokevirtual #2                  // Method "[Lcom/victory/test/object_size/Subject;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Lcom/victory/test/object_size/Subject;"
       9: areturn

  public static com.victory.test.object_size.Subject valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class com/victory/test/object_size/Subject
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #4                  // class com/victory/test/object_size/Subject
       9: areturn

  static {};
    Code:
       0: new           #4                  // class com/victory/test/object_size/Subject
       3: dup
       4: ldc           #7                  // String CHINESE
       6: iconst_0
       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #9                  // Field CHINESE:Lcom/victory/test/object_size/Subject;
      13: new           #4                  // class com/victory/test/object_size/Subject
      16: dup
      17: ldc           #10                 // String MATH
      19: iconst_1
      20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #11                 // Field MATH:Lcom/victory/test/object_size/Subject;
      26: new           #4                  // class com/victory/test/object_size/Subject
      29: dup
      30: ldc           #12                 // String ENGLISH
      32: iconst_2
      33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      36: putstatic     #13                 // Field ENGLISH:Lcom/victory/test/object_size/Subject;
      39: iconst_3
      40: anewarray     #4                  // class com/victory/test/object_size/Subject
      43: dup
      44: iconst_0
      45: getstatic     #9                  // Field CHINESE:Lcom/victory/test/object_size/Subject;
      48: aastore
      49: dup
      50: iconst_1
      51: getstatic     #11                 // Field MATH:Lcom/victory/test/object_size/Subject;
      54: aastore
      55: dup
      56: iconst_2
      57: getstatic     #13                 // Field ENGLISH:Lcom/victory/test/object_size/Subject;
      60: aastore
      61: putstatic     #1                  // Field $VALUES:[Lcom/victory/test/object_size/Subject;
      64: return
}

解释:

  • 从反编译的代码可以看出编译器确实帮我们生成了一个Subject类,该类继承自java.lang.Enum类,生成的这个类是用final修饰的,因此枚举不能被继承,也不能继承其他类了,但是可以实现接口。

  • 声明的每一个枚举常量,都是Subject类的一个实例(见前面几行),这充分说明了前面使用关键字enum定义的类型中的每种Subject枚举常量也是实实在在的Subject实例对象,只不过代表的内容不一样而已。

  • 编译器还生成了两个静态方法,分别是values()和 valueOf(),

  • 接着是编译器生成的静态代码块,后面是静态代码块的JVM指令

到此也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好变量的对应实例对象,同时编译器会为该类创建两个方法,分别是values()和valueOf()。

枚举的常用方法

  • name():是一个实例方法,该方法在java.lang.Enum中,返回枚举的名称,枚举的名称就是定义枚举常量时用的字符串,该方法被final修饰,因此不能被重写
  • values():编译器生成的static方法,按照声明的顺序返回枚举类中定义的所有枚举常量组成的数组,这个方法是一个隐含的方法,由编译器生成的。
  • valueOf(String):编译器生成的static方法,它根据一个名称返回一个枚举常量。
    如果名称所表示的枚举常量不存在,则抛出java.lang.IllegalArgumentException异常。这个方法是一个隐含的方法,由编译器生成的,对于一个具体的枚举类来说,这个方法是有的,但是java.lang.Enum中没有这个方法。
  • valueOf(Class,String):是一个静态的方法,存在于java.lang.Enum中,它的作用跟上一个方法类似,只不过第一个参数是Class类型的,需要指定获取那个类型的常量,第二个参数是常量的名称。
  • getDeclaringClass() :是一个实例方法,存在于java.lang.Enum中,可以获取代表当前枚举类型的Class对象,被final关键字修饰,不能被重写
  • ordinal():是一个实例方法,返回当前枚举常量的序号,序号是在枚举类中声明的顺序,从0开始,最大值是java.lang.Integer.MAX_VALUE,被final关键字修饰,不能被重写。如果枚举常量中的声明位置发生变化,那么ordinal方法获取到的值也随之变化,注意在Effective item35中认为大多数情况下都不应该使用该方法,毕竟它总是变幻莫测的。
  • toString():是一个实例方法,来自于java.lang.Object,在java.lang.Enum的实现是直接返回了name属性,就是name()方法的返回值,这个方法可以被重写。
  • compareTo(E):是一个实例方法,java.lang.Enum类实现了Comparable接口,用于比较当前枚举实例和指定的枚举实例,如果两个枚举实例的类型都不一样,直接会怕抛出异常,否则比较的是他们的ordinal值,这个值是ordinal()方法的返回值,由于这个方法由final修饰,因此不能被重写。

关于作者

来自一线程序员Seven的探索与实践,持续学习迭代中~

本文已收录于我的个人博客:https://www.seven97.top

公众号:seven97,欢迎关注~

标签:实现,object,枚举,victory,test,原理,size,Subject
From: https://www.cnblogs.com/seven97-top/p/18387584

相关文章

  • 仅利用一维数组实现等值线图效果(附完整代码)
    当我们有三个一维数组x,y,i,其中i表示强度(或者其它),用颜色深浅表示。现在我们需要实现以下需求:使用一维数组x、y、i,其中i用于表示颜色深浅。在三维坐标系中,图像位于指定的z轴位置(如z=230)。生成的图像效果类似二维等值线图(ContourPlot)。 那么效果类似怎样的呢?如下图所示......
  • python实现RC4加解密算法
    目录RC4算法简介RC4算法的加密和解密流程RC4算法的Python实现代码解释RC4算法的应用场景RC4的安全性分析总结RC4(RivestCipher4)是一种流加密算法,由RonRivest于1987年设计。RC4广泛应用于各种加密协议,如SSL/TLS和WEP/WPA等。RC4算法因其简单、高效的特点受到广泛关......
  • Python实现SM4加解密算法
    目录SM4算法简介SM4算法的加密和解密流程SM4算法的Python实现代码解释总结SM4算法是中国国家密码局设计的块密码算法,广泛应用于无线局域网标准和其他安全通信系统中。以下是SM4算法的详细介绍,包括加密解密流程和Python的完整实现。SM4算法简介SM4是一种对称分组......
  • Python实现等距映射(ISOMAP)降维算法
    目录Python实现等距映射(ISOMAP)降维算法的博客引言ISOMAP算法原理ISOMAP的优势与局限Python实现ISOMAP算法1.创建ISOMAP类2.在瑞士卷数据集上应用ISOMAP3.结果分析总结运行结果Python实现等距映射(ISOMAP)降维算法的博客引言在高维数据处理中,降维是一种常用的技......
  • 基于Spring Boot的陶瓷文化网站的设计与实现
    毕业设计(论文)论文题目:基于SpringBoot的陶瓷文化网站的设计与实现博主可接毕设论文!!! 摘 要中国悠久的陶瓷艺术,作为民族文化遗产的重要载体,历经时代的洗礼,其文化价值日益凸显。在现代社会变迁中,探寻传统陶瓷文化的传播路径显得尤为重要。随着科技进步与消费模式的革......
  • 基于Springboot公寓电费管理系统的设计与实现(源码+LW+调试文档)
     目录:程序功能截图:程序部分代码参考:数据库sql:程序技术介绍:后端springboot介绍:mysql介绍:程序论文:​选择我的理由:程序获取:......
  • 基于SpringBoot大学生征兵入伍管理系统的设计与实现(源码+LW+调试文档)
     目录:程序功能截图:程序部分代码参考:数据库sql:程序技术介绍:后端springboot介绍:mysql介绍:程序论文:​选择我的理由:程序获取:......
  • 基于python+flask框架的物资捐赠管理平台的管理和实现(开题+程序+论文) 计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在自然灾害频发、社会公益需求日益增长的背景下,物资捐赠作为快速响应社会需求、传递爱心的重要方式,其高效管理和透明化运作显得尤为重要。......
  • java毕业设计-基于springboot+vue的高校自习室预约系统设计和实现,基于springboot+vue
    文章目录前言演示视频项目架构和内容获取(文末获取)项目相关文件系统功能部分实现截图架构设计MVC的设计模式基于B/S的架构技术栈具体功能模块设计系统需求分析可行性分析系统测试为什么我?关于我我自己的网站项目开发案例前言博主介绍:✌️码农一枚,专注于大学生项目......
  • 各种注意力评分函数的实现
    预备知识本文基于MXNet进行实现,需要对于注意力机制有一定初步了解。也需要对Python有足够了解。另外这里稍加说明,在注意力机制中,本质上是“注意”的位置,即加权计算后进行Softmax回归的结果。在Nadaraya-Watson核回归中,首先具有一个键值对(key-value),输入称为一个查询(query),对于......