Java 枚举

原文:https://www.studytonight.com/java-examples/java-enum

枚举(枚举的缩写)是 Java 中的一种特殊数据类型,它包含一组固定的常量。Enum 是一种特殊的类,它扩展了 java.lang.Enum 类。枚举允许我们在编译时知道字段的所有可能值,并使我们的代码更易读。我们可以使用它们来避免由于无效输入而导致的不良行为。例如,方向枚举只能有四个可能的值-北、南、东和西。在本教程中,我们将学习更多关于 Java 中枚举的知识。

创建简单枚举

  • 枚举是通过指定它可以具有的常数值来创建的。
  • 我们使用枚举关键字在 Java 中创建一个枚举。所有枚举常量必须用大写字母 (NORTH,不是 NORTH)书写。
  • 所有枚举常量都是静态最终。静态允许我们通过使用枚举的名称来访问常量。

例子

让我们创建一个简单的枚举来表示学生考试的结果。这个学生可能通过或没有通过考试,也可能缺席考试。

public enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

我们可以通过使用其中一个常量来创建枚举类型的变量。

public class Demo
{
    public static void main(String[] args)
    {
        StudentResult result1 = StudentResult.ABSENT;
        StudentResult result2 = StudentResult.FAIL;
        StudentResult result3 = StudentResult.PASS;

        System.out.println(result1);
        System.out.println(result2);
        System.out.println(result3);
    }
}

缺席 失败 通过

将枚举与 If-Else 语句一起使用

枚举经常与条件语句一起使用,因为它们只能有一个固定的常数值。下面的代码演示了这一点。

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {
        StudentResult result = StudentResult.FAIL;

        if(result == StudentResult.ABSENT)
            System.out.println("The student was absent for the exam.");

        else if(result == StudentResult.PASS)
            System.out.println("The student passed the exam.");

        else if(result == StudentResult.FAIL)
            System.out.println("The student failed the exam.");
    }
}

这个学生考试不及格。

使用带有switch语句的枚举

如果常量的数量更多,那么 switch-case 语句是比 if-else 语句更好的选择。

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {
        StudentResult result = StudentResult.FAIL;

        switch(result)
        {
            case ABSENT : System.out.println("The Student was absent for the exam.");
            break;

            case PASS : System.out.println("The Student passed the exam.");
            break;

            case FAIL : System.out.println("The Student failed the exam.");
            break;
        }
    }
}

这个学生考试不及格。

迭代枚举

我们可以通过使用值()方法获得所有枚举常数的数组。然后,我们可以遍历这个数组并获取单个常量。我们还可以使用序数()方法获取每个常数的数组索引。

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {
        StudentResult[] resultArr = StudentResult.values();

        for(StudentResult sr : resultArr)
        {
            System.out.println(sr + " at index " + sr.ordinal());
        }
    }
}

在指数 0 时通过 在指数 1 时失败 在指数 2 时缺席

枚举的 toString()方法

所有枚举类型都获得一个 toString() 方法,该方法返回枚举常量的字符串值。这允许我们对返回值执行常见的字符串操作。

在下面的代码中,我们首先获取每个常量,并将其转换为字符串。接下来,我们将把它们全部转换成小写并打印出来。

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {    
        for(StudentResult sr : StudentResult.values())
        {
            String resultStr = sr.toString();
            System.out.println("Uppercase: " + resultStr);
            System.out.println("Lowercase: " + resultStr.toLowerCase());
            System.out.println();
        }
    }
}

大写:通过 小写:通过 T3】大写:失败 小写:失败 T6】大写:缺席 小写:缺席

字符串中的枚举

在前一节中,我们学习了如何将枚举常量转换为字符串。我们还可以从字符串值创建枚举类型变量。该转换使用 valueOf() 方法。

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {    
        String resultStr = "FAIL";
        StudentResult result = StudentResult.valueOf(resultStr);
        System.out.print("Enum from String: " + result);
    }
}

字符串中的枚举:失败

如果字符串无效或不代表任何枚举常量,则会引发 IllegalArgumentException

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {    
        String resultStr = "PRESENT";//Invalid enum constant
        StudentResult result = StudentResult.valueOf(resultStr);
    }
}

线程“main”中出现异常 Java . lang . illegalargumentexception:无枚举常量 StudentResult。在 Java . base/Java . lang . enum . value of(enum . Java:273) 的 studentresult . value of(demo . Java:1) 的 Demo.main(Demo.java:13)的 PRESENT

类内枚举

我们还可以在类中定义枚举类型,并将它们用作类的数据成员。在下面的代码中,我们有一个带有名称字段的学生类。让我们在这个类中定义 StudentResult 枚举。我们还将为类的数据成员提供这种枚举类型。让我们也定义一些使用枚举数据成员的方法。

package saddas;

public class Student
{
    String name;
    StudentResult result;

    //Defining an enum type
    enum StudentResult
    {
        PASS,
        FAIL,
        ABSENT;
    }

    //Constructor
    Student(String s, StudentResult sr)
    {
        name = s;
        result = sr;
    }

    //enum if-else method
    public void printResult()
    {
        if(this.result == StudentResult.ABSENT)
            System.out.println(this.name + " was absent for the exam.");

        else if(this.result == StudentResult.PASS)
            System.out.println(this.name + " passed the exam.");

        else
            System.out.println(this.name + " failed the exam.");
    }

    //enum method
    public boolean wasAbsent()
    {
        if(this.result == StudentResult.ABSENT)
            return true;
        else
            return false;
    }

    //main method
    public static void main(String[] args)
    {
        Student s1 = new Student("Justin", StudentResult.ABSENT);
        Student s2 = new Student("Jessica", StudentResult.PASS);

        s1.printResult();
        s2.printResult();

        System.out.println("Student s1 was absent: " + s1.wasAbsent());
    }
}

贾斯汀没有参加考试。 杰西卡通过了考试。 学生 s1 缺席:没错

enumset 集

EnumSet是一种特殊类型的集合,旨在以高效的格式存储枚举常量。枚举使用位向量表示来存储枚举常数。EnumSet 可以执行所有常规的 Set 操作。在使用枚举类型时,总是建议首选EnumSet而不是常规集。我们可以使用()方法创建所选常数的枚举。或者我们可以使用 allOf()方法来创建集合中所有常数的枚举。

import java.util.EnumSet;

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {
        EnumSet resultSet1 = EnumSet.of(StudentResult.FAIL, StudentResult.PASS);
        EnumSet resultSet2 = EnumSet.allOf(StudentResult.class);

        System.out.println("Enum Set-1: " + resultSet1);
        System.out.print("Enum Set-2: " + resultSet2);
    }
}

EnumSet-1:[通过,失败] EnumSet-2:[通过,失败,缺席]

枚举

EnumMap是为枚举类型设计的特殊映射实现。EnumMaps 存储键-值对,其中键总是 enum 常量,值可以是任何类型。就像枚举一样,在存储枚举方面,EnumMap比普通的HashMap更好、更有效。我们可以在 EnumMap 上执行所有正常的映射操作。

import java.util.EnumMap;
import java.util.Map;

enum StudentResult
{
    PASS,
    FAIL,
    ABSENT;
}

public class Demo
{
    public static void main(String[] args)
    {
        EnumMap<StudentResult, String> resultMap = new EnumMap<>(StudentResult.class);
        resultMap.put(StudentResult.PASS, "Student Passed the exam");
        resultMap.put(StudentResult.FAIL, "Student Failed the exam");
        resultMap.put(StudentResult.ABSENT, "Student was absent for the exam");

        for(Map.Entry<StudentResult, String> e : resultMap.entrySet())
            System.out.println(e.getKey() + " --> " + e.getValue());
    }
}

及格- >学生通过考试 不及格- >学生考试不及格 缺课- >学生考试缺课

枚举字段

我们可以向枚举类型添加一个字段或数据成员。该字段将与每个常数相关联。我们可以使用构造器为每个常量初始化这个枚举字段。

例如,在下面的代码中,我们向枚举添加了一个String类型的百分比字段。我们还为这个字段编写了一个构造器。所有枚举常数都用不同的参数调用了此构造器。

请注意,枚举的构造器总是私有的。我们不能使用任何其他修饰语。如果未指定访问修饰符,则隐式添加 Private。

enum StudentResult
{    
    PASS("Above 35%"),//Constructor called with value "Above 35%"
    FAIL("Below 35%"),//Constructor called with value "Below 35%"
    ABSENT("N/A");//Constructor called with value "N/A"

    String percent; //Enum Field

    private StudentResult(String percent)//Private constructor
    {
        this.percent = percent;
    }
}

public class Demo
{
    public static void main(String[] args)
    {
        for(StudentResult s : StudentResult.values())
            System.out.println(s + " -> " + s.percent);
    }
}

通过- >高于 35% 未通过- >低于 35% 缺席- >不适用

枚举方法

枚举可以包含具体抽象方法。对于抽象方法,枚举的每个实例或常数都必须实现它。让我们看一下这两种场景的示例。

具体方法

让我们在枚举中添加一个 print()方法。这将打印枚举常数和常数的百分比字段。

enum StudentResult
{
    PASS("Above 35%"),//Constructor called with value "Above 35%"
    FAIL("Below 35%"),//Constructor called with value "Below 35%"
    ABSENT("N/A");//Constructor called with value "N/A"

    String percent; //Enum Field

    private StudentResult(String percent)//Private constructor
    {
        this.percent = percent;
    }

    //Enum Method
    public void print()
    {
        System.out.println(this + " --> " + this.percent);
    }
}

public class Demo
{
    public static void main(String[] args)
    {
        for(StudentResult s : StudentResult.values())
            s.print();
    }
}

通过- >高于 35% 未通过- >低于 35% 缺席- >不适用

抽象方法

让我们将 print()方法抽象化。现在,每个常量都应该覆盖它。

enum StudentResult
{
    PASS("Above 35%"){
        //Override the abstract print method
        @Override 
        void print() {
            System.out.println("Pass(Above 35%)");
        }
    },
    FAIL("Below 35%"){
        //Override the abstract print method
        @Override 
        void print() {
            System.out.println("Fail(Below 35%)");
        }
    },
    ABSENT("N/A"){
        //Override the abstract print method
        @Override 
        void print() {
            System.out.println("Absent for the exam");
        }
    };

    String percent;//Enum field

    StudentResult(String percent)//private constructor
    {
        this.percent = percent;
    }

    //Abstract Enum Method
    abstract void print();
}

public class Demo
{
    public static void main(String[] args)
    {
        for(StudentResult s : StudentResult.values())
            s.print();
    }
}

及格(35%以上) 不及格(35%以下) 缺考

实现接口

枚举类型不能扩展其他类,因为它隐式扩展了 java.lang.Enum 类。但是,它可以实现其他接口。下面的代码演示了这一点。

interface DemoInterface
{
    void print();
}

enum StudentResult implements DemoInterface
{
    PASS("Above 35%"),//Constructor called with value "Above 35%"
    FAIL("Below 35%"),//Constructor called with value "Below 35%"
    ABSENT("N/A");//Constructor called with value "N/A"

    String percent;//Enum Field

    private StudentResult(String percent)//Private constructor
    {
        this.percent = percent;
    }

    //implementing the interface method
    @Override
    public void print()
    {
        System.out.println(this + " --> " + this.percent);
    }
}

public class Demo
{
    public static void main(String[] args)
    {
        for(StudentResult s : StudentResult.values())
            s.print();
    }
}

通过- >高于 35% 未通过- >低于 35% 缺席- >不适用

摘要

枚举用于定义常量值的集合。以下几点总结了本教程中学习的关键概念。

  • 它们非常类似于具有最终成员和静态成员的类。
  • 枚举使用最终类在内部实现。每个枚举常数都是该类的静态和最终数据成员。
  • 编译器在内部将 values()、valueOf()和序数()方法添加到我们的枚举中。
  • 枚举还可以包含其他字段和构造器来初始化这些字段。
  • 构造器必须始终是私有的,我们不能使用 new 关键字来创建枚举的实例。
  • 枚举也可以包含具体的和抽象的方法。枚举实例必须为抽象方法实现。
  • Enum 隐式扩展了 java.lang.Enum 类,因此不能扩展任何其他类。但是它们可以实现其他接口。
  • 它们提高了类型安全性,因为编译器确切地知道枚举类型实例的常量。