Java枚举类型

article/2025/10/11 19:25:34

目录

一、前言:

二、枚举类型:

三、底层原理

四、应用

应用一:定义常量

底层原理详解

应用二:添加新方法

应用三:与switch结合使用

应用四:实现接口

应用五:使用接口组织枚举


一、前言

回想单例设计模式:单例类是一个类只有一个实例,那么多例类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例,这才能是枚举类。 枚举类是把变量的值一一列出来,变量的值只限于列举出来的值的范围内。

二、枚举类型

  1. 在Java中,被 enum 关键字修饰的类型就是枚举类型,enum 的全称为 enumeration,它是 JDK 1.5 中引入的新特性。所有的枚举类型都是继承自Enum 类型。 
  2. 它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,因此这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。
  3. 枚举一般用于以下情况:定义常量、添加新方法、与switch结合使用、实现接口、使用接口组织枚举。

     下面使用枚举定义常量,并对比未使用枚举定义常量的区别,同时介绍枚举的基本原理。

三、底层原理

     见底层原理详解。

四、应用

   应用一:定义常量

    案例:未使用枚举类型定义常量

    我们通常利用public final static 方法定义的代码如下,分别用1-6表示星期一到星期日

public class EnumWeekDay {

    public static final int MONDAY =1;

    public static final int TUESDAY=2;

    public static final int WEDNESDAY=3;

    public static final int THURSDAY=4;

    public static final int FRIDAY=5;

    public static final int SATURDAY=6;

    public static final int SUNDAY=7;
    
    public static void main(String[] args) {
      System.out.println(EnumWeekDay .MONDAY);
      System.out.println(EnumWeekDay .WEDNESDAY);
      System.out.println(EnumWeekDay .THURSDAY);
      System.out.println(EnumWeekDay .FRIDAY);
      System.out.println(EnumWeekDay .SATURDAY);
      System.out.println(EnumWeekDay .SUNDAY);
    }

}

问题:上述的常量定义常量的方式称为int枚举模式,这样的定义方式在类型安全和使用方便性上有不足之处,如果存在定义int值相同的变量,混淆的几率很大,编译器也不会提出任何警告。
解决方案:使用枚举类型
      枚举类型现后上述int枚举模式并不提倡,相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法,现在我们利用枚举类型来重新定义上述的常量。

      案例:使用枚举类型之后定义常量

enum EnumWeekDay {
    //使用枚举方式,会自动赋值,默认值是从0开始
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

进行测试:

public class WeekDayDemo {
    public static void main(String[] args) {
         //结果本质上都是EnumWeekDay对象,底层相当于调用了EnumWeekDay默认构造方法创建一个对象,将所有的数据存入数组
        System.out.println(EnumWeekDay.MONDAY.getClass().getName());
        System.out.println(EnumWeekDay.MONDAY);
        System.out.println(EnumWeekDay.TUESDAY);
        System.out.println(EnumWeekDay.WEDNESDAY);
        System.out.println(EnumWeekDay.THURSDAY);
        System.out.println(EnumWeekDay.FRIDAY);
        System.out.println(EnumWeekDay.SATURDAY);
        System.out.println(EnumWeekDay.SUNDAY);
        System.out.println(EnumWeekDay.SUNDAY);

        System.out.println(EnumWeekDay.MONDAY.ordinal());
        System.out.println(EnumWeekDay.TUESDAY.ordinal());
        System.out.println(EnumWeekDay.WEDNESDAY.ordinal());
        System.out.println(EnumWeekDay.THURSDAY.ordinal());
        System.out.println(EnumWeekDay.FRIDAY.ordinal());
        System.out.println(EnumWeekDay.SATURDAY.ordinal());
        System.out.println(EnumWeekDay.SUNDAY.ordinal());
    }
}

运行结果com.JavaSe.emum.EnumWeekDay
星期一
星期二
星期三
星期四
星期五
星期六
星期日
0
1
2
3
4
5
6

       通过案例可以看出,使用枚举的结果本质上底层调用了EnumWeekDay默认构造方法,创建了多个EnumWeekDay实例对象,对象起名分别为MONDAY到SUNDAY,将枚举数据实例存入一个数组的里面,ordinal是数组的下标。(后面原理部分会讲)

       案例:使用枚举的有参构造

步骤:

  1. 先定义枚举实例序列,枚举实例后的括号,表示调用私有构造方法;
  2. 必须在enum实例序列的最后添加一个分号;
  3. 创建私有变量;
  4. 编写私有有参构造方法;
  5. 覆盖toString()方法

public enum EnumWeekDay {
    //1、定义枚举常量, 2、并添加分号
    MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"),
    THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六"), SUNDAY("星期日");

    // 3、创建私有变量;
    private String weekday;

    //4、编写私有有参构造方法;
    private EnumWeekDay(String weekday) {
        System.out.println(weekday);
        this.weekday = weekday;
    }
    //5、覆盖toString()方法
    @Override
    public String toString() {
        return this.weekday;
    } 

}

运行结果星期一
星期二
星期三
星期四
星期五
星期六
星期日

底层原理详解

       实际上在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,
这个类继承了Java API中的java.lang.Enum类。以上面案例为例:使用javac进行编译EnumWeekDay.java:javac EnumWeekDay.java,生成EnumWeekDay.class,对EnumWeekDay.class反编译如下:

public enum EnumWeekDay  {

   MONDAY("星期一"), 
   TUESDAY("星期二"), 
   WEDNESDAY("星期三"),
   THURSDAY("星期四"), 
   FRIDAY("星期五"), 
   SATURDAY("星期六"), 
   SUNDAY("星期日");
   
   private String weekday;
   
   // $FF: synthetic field
   private static final EnumWeekDay[] $VALUES 
           = new EnumWeekDay[]{MONDAY, TUESDAY, WEDNESDAY,
             THURSDAY, FRIDAY, SATURDAY, SUNDAY};

   private EnumWeekDay(String var3) {
      System.out.println(var3);
      this.weekday = var3;
   }

   public String toString() {
      return this.weekday;
   }
}

再进一步分析:

final class EnumWeekDay extends Enum {
    private String weekday;
    //私有构造函数
    private EnumWeekDay(String name)
    {
      this.weekday =weekday;
    }

    //前面定义的7种枚举实例
    public static final EnumWeekDay MONDAY;
    public static final EnumWeekDay TUESDAY;
    public static final EnumWeekDay WEDNESDAY;
    public static final EnumWeekDay THURSDAY;
    public static final EnumWeekDay FRIDAY;
    public static final EnumWeekDay SATURDAY;
    public static final EnumWeekDay SUNDAY;
    private static final EnumWeekDay  $VALUES[];

    static
    {
        //实例化枚举实例
        MONDAY = new EnumWeekDay("星期一");
        TUESDAY = new EnumWeekDay("星期二");
        WEDNESDAY = new EnumWeekDay("星期三");
        THURSDAY = new EnumWeekDay("星期四");
        FRIDAY = new EnumWeekDay("星期五");
        SATURDAY = new EnumWeekDay("星期六");
        SUNDAY = new EnumWeekDay("星期日");
        $VALUES = (new EnumWeekDay[] {
                MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });

    }

    //编译器为我们添加的静态的values()方法
    public static EnumWeekDay[] values()
    {
        return (EnumWeekDay[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static EnumWeekDay valueOf(String s)
    {
        return (EnumWeekDay)Enum.valueOf(./EnumWeekDay, s);
    }

}

       从反编译的代码看出,EnumWeekDay类(注意该类是final类型的,将无法被继承)继承自java.lang.Enum类,同时编译器还帮助我们生成了7个EnumWeekDay类型的实例对象分别对应枚举中定义的7个日期,充分说明了使用关键字enum定义的EnumWeekDay类型中的每种日期枚举常量也是实实在在的EnumWeekDay实例对象。

        类中values()方法的作用就是获取枚举类中的所有变量,并作为数组返回,valueOf()根据参数获取1个对应枚举变量,测试用例如下: 

for (EnumWeekDay weekDay:EnumWeekDay.values()) {
    System.out.println(weekDay);
}

System.out.println(EnumWeekDay.valueOf("MONDAY"));

应用二:添加新方法

   Java 为枚举类型提供了一些内置的方法,同时枚举常量也可以有自己的方法。此时要注意必须在枚举实例的最后一个成员后添加分号,而且必须先定义枚举实例。

步骤:

  1. 先定义枚举实例序列,枚举实例后的括号,表示调用私有构造方法;
  2. 必须在enum实例序列的最后添加一个分号;
  3. 创建私有变量;
  4. 编写私有有参构造方法;
  5. 添加新方法;
  6. 覆盖toString()方法。

public enum EnumWeekDay {
    //1、定义枚举常量, 2、并添加分号
    MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"),
    THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六"), SUNDAY("星期日");
    // 3、创建私有变量;
    private String weekday;

    //4、编写私有有参构造方法;
    private EnumWeekDay(String weekday) {
        System.out.println(weekday);
        this.weekday = weekday;
    }
    //5、覆盖toString()方法
    @Override
    public String toString() {
        return this.weekday;
    }
    //6、添加新方法
    public static EnumWeekDay getWeekDay(int num) {
         switch(i) {
            case 1:
                return EnumWeekDay.MONDAY;
            case 2:
                return EnumWeekDay.TUESDAY;
            case 3:
                return EnumWeekDay.WEDNESDAY;
            case 4:
                return EnumWeekDay.THURSDAY;
            case 5:
                return EnumWeekDay.FRIDAY;
            case 6:
                return EnumWeekDay.SATURDAY;
            case 7:
                return EnumWeekDay.SUNDAY;
            default:
                System.out.println("wrong number!");
                return null;
        }
    }
}

class EnumWeekDayDemo{public static void main(String[] args) {System.out.println(EnumWeekDay.getWeekDay(1).toString());System.out.println(EnumWeekDay.getWeekDay(2).toString());System.out.println(EnumWeekDay.getWeekDay(3).toString());System.out.println(EnumWeekDay.getWeekDay(4).toString());System.out.println(EnumWeekDay.getWeekDay(5).toString());System.out.println(EnumWeekDay.getWeekDay(6).toString());System.out.println(EnumWeekDay.getWeekDay(7).toString());}
}
运行结果星期一
星期二
星期三
星期四
星期五
星期六
星期日

应用三:与switch结合使用

       关于使用switch进行条件判断时,条件参数一般只能是整型,字符型。而枚举型确实也被switch所支持,在java 1.7后switch也对字符串进行了支持。这里我们简单看一下switch与枚举类型的使用:

public enum EnumWeekDay {
    //1、定义枚举常量, 2、并添加分号
    MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"),
    THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六"), SUNDAY("星期日");
    // 3、创建私有变量;
    private String weekday;

    //4、编写私有有参构造方法;
    private EnumWeekDay(String weekday) {
        System.out.println(weekday);
        this.weekday = weekday;
    }
    //5、覆盖toString()方法
    @Override
    public String toString() {
        return this.weekday;
    }  
}

与switch结合测试类:

public class WeekDayDemo {
    public static void main(String[] args) {
        EnumWeekDay weekDay = EnumWeekDay .MONDAY;
        getDay(weekDay);
    }

    public static void getDay(EnumWeekDay weekDay){
        switch (weekDay){
            case MONDAY:
                System.out.println(MONDAY);
                break;
            case TUESDAY:
                System.out.println(TUESDAY);
                break;
            case WEDNESDAY:
                System.out.println(WEDNESDAY);
                break;
            case THURSDAY:
                System.out.println(THURSDAY);
                break;
            case FRIDAY:
                System.out.println(FRIDAY);
                break;
            case SATURDAY:
                System.out.println(SATURDAY);
                break;
            case SUNDAY:
                System.out.println(SUNDAY);
                break;
            default:
                System.out.println("输入有误");
                break;
        }
    }
}

应用四:实现接口

       由于Java单继承的原因,enum类并不能再继承其它类,但并不妨碍它实现接口,因此enum类同样是可以实现多接口的,如下:

interface food{
    void eat();
}

interface sport{
    void run();
}

public enum EnumDemo2 implements food ,sport{
    FOOD,
    SPORT,
    ; //分号分隔

    @Override
    public void eat() {
        System.out.println("eat.....");
    }

    @Override
    public void run() {
        System.out.println("run.....");
    }

    public static void main(String[] args) {
        EnumDemo2.FOOD.eat();
        EnumDemo2.SPORT.run();
    }
}

应用五:使用接口组织枚举

       有时候,我们可能需要对一组数据进行分类,比如对食物分类,食物包含dessert(点心)、Coffee等,而且希望这些都属于food类型,此时可以利用接口来组织,因此利用一个枚举嵌套枚举的方式,可以统一管理食物中的数据了。如下(代码引用自Thinking in Java):

public interface Food {  
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}
public class TypeOfFood {
   public static void main(String[] args) {
      Food food = Dessert.GELATO;
      food = Coffee.CAPPUCCINO;
  }



 


http://chatgpt.dhexx.cn/article/sUhmKc0c.shtml

相关文章

深入理解Java枚举类型(enum)

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/71333103 出自【zejian的博客】 关联文章: 深入理解Java类型信息(Class对象)与反射…

Python中对基本文件操作

Python中对基本文件操作 一、前言二、创建和打开文件1.打开一个不存在的文件时先创建该文件2.以二进制形式打开文件3.打开文件时指定编码方式 三、关闭文件四、打开文件时使用with语句五、写入文件内容六、读取文件1.读取指定字符2.读取一行3.读取全部行 一、前言 在Python中&a…

C语言——文件操作

文章目录 1. 为什么使用文件2. 什么是文件2.1 程序文件2.2 数据文件2.3 文件名 3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭 4. 文件的顺序读写4.1 fgetc与fputc4.2 fgets与fputs4.3 fscant与fprintf4.3.1 fprintf4.3.2 fscanf 4.4 fread与fwrite4.4.1 fwrite4.4.2 f…

C语言之文件操作

目录 为什么使用文件 文件名 文件指针 流 文件的打开和关闭 前言 文件的打开方式 文件打开关闭函数 fopen函数 fclose函数 文件的顺序读写 fputc函数 fgetc函数 fputs函数 fgets函数 fprintf函数 fscanf函数 fwrite函数 fread函数 文件的随机读写 fseek函…

文件操作(图解)

文件操作 1、文件是什么?1.1 程序文件1.2 数据文件1.3 文件名 2、文件的打开和关闭2.1 文件指针2.2 文件的打开和关闭 3、文件的顺序读写4、文件的随机读写4.1 fseek4.2 ftell4.3 rewind 5、文本文件和二进制文件6、文件读取结束的判定6.1 被错误使用的feof 7、文件…

C++中的文件操作

目录 文件操作C中的文件操作时基于面向对象的C中文件类型分为两种:操作文件的三大类(这些类都属于标准模板库):1 文本文件1.1 写文件写文件步骤如下:文件打开方式: 1.2 读文件读取文件数据的四种方式按照喜好记前三个中…

什么是文件操作?为什么要有文件操作?

文章目录 前言一、什么是文件1.1 程序文件1.2 数据文件 二、文件的打开与关闭2.1 文件指针2.2 文件的打开与关闭2.3 文件读写详情表!(重点)2.4 文件的顺序读写!(重点)2.5 文件的随机读写2.5.1 fseek2.5.2 f…

常见文件操作函数

目录 一、文件的打开和关闭 1、文件指针 2、文件打开和关闭 二、文件的顺序读写 1、fgetc()和fputc()函数 2、fgets()和fputs()函数 3、fscanf()和fprintf()函数 4、fread()和fwrite()函数 三、文件的随机读写 1、fseek函数 2、ftell函数 3、rewind函数 四、文本文…

【Linux】Linux的文件操作

文件操作对于不少编程初学者来说都是一件头疼的事情,不管你学习的是什么编程语言,C/C/Java/Go/Python ,因为我们学习到的文件相关的操作对你来说都是一个黑盒,我们只是知道我们应该怎么使用相应的文件函数进行操作,而对于内部的实…

文件操作(详解)

目录 1. 为什么使用文件 2. 什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3. 文件的打开和关闭 3.1 文件指针 ​ 3.2 文件的打开和关闭 4. 文件的顺序读写 4.1 对比一组函数: 5. 文件的随机读写 5.1 fseek 5.2 ftell 5.3 rewind 7. 文件读取结束的…

c语言中的文件操作

目录 引入: 一、文件的打开和关闭 1.文件名 2.文件指针 3.文件的打开和关闭 二、对文件如何操作和流 1.对文件操作相关功能: 2.流 三、文件操作函数(顺序读写) 1."w"输出流: 2."r" 输入流 3."wb"与&…

C语言 文件操作

文件操作在我们的使用中虽然占的不多,但是有些时候,还是需要这部分的知识的。比如,我们做了一个C语言版的售卖系统。现在的想法是在关闭的时候保存这次的结果,然后下一次继续使用,这个时候,就可以使用文件操…

手把手教你学Python之文件操作(一文掌握文件操作)

目录 1、Python中文本文件的读写 2、Python中常用的文件与文件夹操作方法 3、Python中Excel文件的读写 4、Python读取Excel文件案例​ 为了保存数据,方便修改和分享,数据通常以文件的形式存储在磁盘等外部存储介质中。根据逻辑上编码不同可将文件大致…

Linux文件操作

目录 一、系统api与库函数的关系二、open和close函数介绍2.1 open方法介绍2.2 close方法介绍 三、open/create函数创建文件时的权限设置四、read和write函数的介绍和使用4.1 read函数介绍4.2 write函数介绍4.3 如何使用 五、lseek函数的介绍和使用5.1 介绍5.2 如何使用 六、阻塞…

python文件操作(一看就懂)

python文件操作 历史遗留问题文件介绍打开文件转定义字符Python格式化字符串的替代符以及含义Python的转义字符及其含义 💕Final~ 历史遗留问题 现在我们接着上文讲,如果没有看过我上篇文章的萌新朋友们可以先去看看,不然一会儿容易读的你满…

Linux的文件操作命令

接下来将介绍Linux中一些常用的文件操作命令,今天先演示五个类型的命令操作,内容不是特别的全,找的几个典型的常用的演示,想要全面的可以另找资料了解一下,推荐大家跟着敲跟着做才能加深记忆,祝大家学的开心…

Linux —— 文件操作

目录 1.内核提供的文件系统调用 1.1open和close 1.2标记位 1.3write和read 2.文件描述 2.1文件描述符 2.2文件描述符分配规则 3.重定向 3.1最“挫”的重定向 3.2使用系统调用 3.3重定向原理 3.4让我们的"shell"支持重定向操作 4.一切皆文件 5.缓冲区 5…

文件操作详解

1.文件的概念 文件的基本概念   所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁…

文件操作(C语言)

目录 一、前言 二、文件的打开和关闭 三、文件的读写 1.文件的顺序读写 2.文件的随机读写 四、文件结束的判定 一、前言 当我们向写好的通讯录程序中输入信息时,有时我们希望能保存输入的信息,不用每次打开这个程序都要重新输入,这时就…

文件操作详解(超级详细)

正常我们的程序在执行的时候程序结束后,会将所有数据清楚,那么我们应该如何保存数据呢?这里我们就需要用文件操作。 一、文件的打开和关闭 1.文件打开、关闭函数—fopen、fclose //打开文件 FILE * pf fopen ( const char * filename, const…