Java中"enum"的用途是什么?

Zim*_*Zim 66 java enums

所以,我看着这个"枚举"类型,并且它种好像一个华而不实的数组/ArrayList/ List给我.它的用途究竟是什么?

aio*_*obe 72

如果类应具有固定的可枚举实例数,则使用a enum而不是a .class

例子:

  • DayOfWeek  = 7个实例→ enum
  • CardSuit    = 4个实例→ enum
  • Singleton  = 1个实例→ enum

  • Product      =可变数量的实例→ class
  • User            =可变数量的实例→ class
  • Date            =可变数量的实例→ class


use*_*882 70

枚举作为一种固定数量的常量,至少可以用于两件事

不变

public enum Month {
    JANUARY, FEBRUARY, ...
}
Run Code Online (Sandbox Code Playgroud)

这比创建一堆整数常量要好得多.

创建一个单身人士

public enum Singleton {
    INSTANCE

   // init
};
Run Code Online (Sandbox Code Playgroud)

你可以用枚举做很有趣的事情,看看这里

另请查看官方文档

  • @Tomas 我不会说 [Singleton](http://en.wikipedia.org/wiki/Singleton_pattern) 的用法“完全不同”。程序员的意图可能有所不同,因为单例通常在应用程序中扮演更大的角色,而多值枚举通常是一些小的具体细节。也许这就是您的评论的意图。但从技术上讲,单例枚举只是一个“固定的常量列表”,它恰好只有一个元素。正如 aioobe 所问的那样,从技术上讲,此答案中的两个示例完全相同;一个是具有 12 个值的枚举,另一个具有 1 个值。 (2认同)

Ran*_*Lin 46

枚举类型基本上是一种数据类型,它允许您以更可读和可靠的方式描述类型的每个成员.

这是一个简单的例子来解释原因:

假设您正在编写一个与季节有关的方法:

int枚举模式

首先,您声明了一些int静态常量来表示每个季节.

public static final int SPRING = 0;
public static final int SUMMER = 1;
public static final int FALL = 2;
public static final int WINTER = 2;
Run Code Online (Sandbox Code Playgroud)

然后,您声明了一种方法,以将季节名称打印到控制台中.

public void printSeason(int seasonCode) {
    String name = "";
    if (seasonCode == SPRING) {
        name = "Spring";
    }
    else if (seasonCode == SUMMER) {
        name = "Summer";
    }
    else if (seasonCode == FALL) {
        name = "Fall";
    }
    else if (seasonCode == WINTER) {
        name = "Winter";
    }
    System.out.println("It is " + name + " now!");
}
Run Code Online (Sandbox Code Playgroud)

那么,之后,您可以打印这样的季节名称.

printSeason(SPRING);
printSeason(WINTER);
Run Code Online (Sandbox Code Playgroud)

对于类中不同类型的成员,这是一种非常常见(但不好)的方法.但是,由于这些代码涉及整数,因此您也可以毫无问题地调用此方法.

printSeason(0);
printSeason(1);
Run Code Online (Sandbox Code Playgroud)

或者甚至喜欢这个

printSeason(x - y);
printSeason(10000);
Run Code Online (Sandbox Code Playgroud)

编译器不会抱怨,因为这些方法调用是有效的,并且您的printSeason方法仍然可以工作.

但有些事情并不恰到好处.季节代码10000应该是什么意思?如果x - y导致负数怎么办?当你的方法收到一个没有意义且不应该在那里的输入时,你的程序对它一无所知.

您可以通过添加其他检查来解决此问题.

...
else if (seasonCode == WINTER) {
    name = "Winter";
}
else {
    throw new IllegalArgumentException();
}
System.out.println(name);
Run Code Online (Sandbox Code Playgroud)

现在程序将RunTimeException在季节代码无效时抛出.但是,您仍需要决定如何处理异常.

顺便说一句,我相信你注意到了代码,FALL并且WINTER都是2,对吗?

你现在应该明白这个想法.这种模式很脆弱.它让你在任何地方写条件检查.如果你正在制作一个游戏,并且想要在你想象的世界中增加一个额外的季节,这个模式将让你通过所有按季节做事的方法,并且在大多数情况下你会忘记其中的一些.

您可能认为类继承对于这种情况是个好主意.但我们只需要其中一些而不是更多.

那是什么时候enum发挥作用.


使用enum类型

在Java中,enum类型是通过公共静态最终字段为每个枚举常量导出一个实例的类.

在这里你可以声明四个枚举常量:SPRING, SUMMER, FALL, WINTER.每个都有自己的name.

public enum Season {
    SPRING("Spring"), SUMMER("Summer"), FALL("Fall"), WINTER("Winter");

    private String name;

    Season(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,回到方法.

public void printSeason(Season season) {
    System.out.println("It is " + season.getName() + " now!");
}
Run Code Online (Sandbox Code Playgroud)

int您现在可以将其Season用作输入,而不是使用.您可以告诉Season它给你的名字,而不是条件检查.

这就是你现在使用这个方法的方法:

printSeason(Season.SPRING);
printSeason(Season.WINTER);
printSeason(Season.WHATEVER); <-- compile error
Run Code Online (Sandbox Code Playgroud)

当您使用不正确的输入时,您将收到编译时错误,并且Season只要程序编译,您就可以保证获得非空的单例引用.

当我们需要一个额外的季节时,我们只需添加另一个常数,Season而不是更多.

public enum Season {
    SPRING("Spring"), SUMMER("Summer"), FALL("Fall"), WINTER("Winter"), 
    MYSEASON("My Season");

...
Run Code Online (Sandbox Code Playgroud)

无论什么时候需要一组固定的常量,enum都可以是一个不错的选择(但并非总是如此).它是一个更具可读性,更可靠和更强大的解决方案.


Ash*_*hir 27

枚举类型是一种类型,其字段由一组固定的常量组成.常见示例包括罗盘方向(NORTH,SOUTH,EAST和WEST的值)和星期几.

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
}
Run Code Online (Sandbox Code Playgroud)

您需要在需要表示一组固定常量时使用枚举类型.这包括自然枚举类型,例如太阳系中的行星和数据集,您可以在编译时知道所有可能的值 - 例如,菜单上的选项,命令行标志等.

以下是一些代码,向您展示如何使用上面定义的Day枚举:

public class EnumTest {
    Day day;

    public EnumTest(Day day) {
        this.day = day;
    }

    public void tellItLikeItIs() {
        switch (day) {
            case MONDAY:
                System.out.println("Mondays are bad.");
                break;

            case FRIDAY:
                System.out.println("Fridays are better.");
                break;

            case SATURDAY: case SUNDAY:
                System.out.println("Weekends are best.");
                break;

            default:
                System.out.println("Midweek days are so-so.");
                break;
        }
    }

    public static void main(String[] args) {
        EnumTest firstDay = new EnumTest(Day.MONDAY);
        firstDay.tellItLikeItIs();
        EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
        thirdDay.tellItLikeItIs();
        EnumTest fifthDay = new EnumTest(Day.FRIDAY);
        fifthDay.tellItLikeItIs();
        EnumTest sixthDay = new EnumTest(Day.SATURDAY);
        sixthDay.tellItLikeItIs();
        EnumTest seventhDay = new EnumTest(Day.SUNDAY);
        seventhDay.tellItLikeItIs();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

星期一很糟糕.
周中的日子一般般.
星期五更好.
周末最好.
周末最好.

Java编程语言枚举类型比其他语言中的对应类型更强大.枚举声明定义了一个类(称为枚举类型).枚举类主体可以包括方法和其他字段.编译器在创建枚举时会自动添加一些特殊方法.例如,它们有一个静态值方法,该方法返回一个数组,该数组按照声明的顺序包含枚举的所有值.此方法通常与for-each构造结合使用,以迭代枚举类型的值.例如,下面Planet类示例中的代码迭代太阳系中的所有行星.

for (Planet p : Planet.values()) {
    System.out.printf("Your weight on %s is %f%n",
                      p, p.surfaceWeight(mass));
}
Run Code Online (Sandbox Code Playgroud)

除了它的属性和构造函数之外,Planet还有一些方法可以让您检索每个行星上物体的表面重力和重量.这是一个示例程序,它可以减轻地球上的重量(在任何单位)并计算并打印所有行星上的重量(在同一单位):

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass() { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: java Planet <earth_weight>");
            System.exit(-1);
        }
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
}
Run Code Online (Sandbox Code Playgroud)

如果从命令行运行Planet.class,参数为175,则会得到以下输出:

$ java Planet 175
你在MERCURY上的体重是66.107583
你在VENUS的体重是158.374842
你在EARTH的体重是175.000000
你在MARS的体重是66.279007
在JUPITER的体重是442.847567
你的体重在SATURN是186.552719
你的体重在URANUS是158.397260
你的体重在NEPTUNE是199.207413

资料来源:http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

  • 您至少可以编写一个源代码,因为您无需更改即可复制粘贴官方文档. (16认同)