Java中“enum”的用途是什么?

What's the use of “enum” in Java?

本问题已经有最佳答案,请猛点这里访问。

所以我研究了这个"枚举"类型,在我看来它有点像一个美化的数组/ArrayList/List。它的具体用途是什么?


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

实例:

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

    >

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


枚举作为固定数量的常量的一种类型,至少可以用于两个方面

常数

1
2
3
public enum Month {
    JANUARY, FEBRUARY, ...
}

这比创建一组整型常量要好得多。

创建单例

1
2
3
4
5
public enum Singleton {
    INSTANCE

   // init
};

你可以用Enums做一些有趣的事情,看这里

还要看官方文件


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

下面是一个简单的例子来解释为什么:

假设你写的方法与季节有关:

int枚举模式

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

1
2
3
4
public static final int SPRING = 0;
public static final int SUMMER = 1;
public static final int FALL = 2;
public static final int WINTER = 2;

然后,您声明了将季节名称打印到控制台中的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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!");
}

所以,在那之后,你可以打印这样的季节名称。

1
2
printSeason(SPRING);
printSeason(WINTER);

对于一个类中不同类型的成员,这是一种非常常见(但很糟糕)的方法来做不同的事情。但是,由于这些代码涉及整数,所以您也可以这样调用方法,而不会有任何问题。

1
2
printSeason(0);
printSeason(1);

或者像这样

1
2
printSeason(x - y);
printSeason(10000);

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

但这里有点不对劲。10000的季节代码应该是什么意思?如果x - y产生负数怎么办?当您的方法接收到一个没有意义且不应该存在的输入时,您的程序对它一无所知。

例如,您可以通过添加附加检查来解决此问题。

1
2
3
4
5
6
7
8
...
else if (seasonCode == WINTER) {
    name ="Winter";
}
else {
    throw new IllegalArgumentException();
}
System.out.println(name);

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

顺便问一下,我确信你注意到FALLWINTER的代码都是2,对吗?

你现在应该明白了。这种图案很脆。它使您可以在任何地方编写条件检查。如果你正在做一个游戏,并且你想在你想象的世界里增加一个额外的赛季,这个模式会让你通过所有按赛季做事情的方法,在大多数情况下,你会忘记其中的一些。

对于这种情况,您可能认为类继承是一个好主意。但我们只需要其中的一部分,不再需要了。

这时,enum开始发挥作用。

使用enum

在爪哇中,EDCOX1×12种类型是通过公共静态最终字段为每个枚举常量导出一个实例的类。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
    }
}

现在,回到方法上来。

1
2
3
public void printSeason(Season season) {
    System.out.println("It is" + season.getName() +" now!");
}

现在可以使用Season作为输入,而不是使用int。你可以告诉Season给你名字,而不是条件检查。

这就是您现在如何使用此方法:

1
2
3
printSeason(Season.SPRING);
printSeason(Season.WINTER);
printSeason(Season.WHATEVER); <-- compile error

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

当我们需要一个额外的季节时,我们只需在Season中添加另一个常量,而不再添加。

1
2
3
4
5
public enum Season {
    SPRING("Spring"), SUMMER("Summer"), FALL("Fall"), WINTER("Winter"),
    MYSEASON("My Season");

...

每当需要一组固定的常量时,enum是一个不错的选择(但并非总是如此)。它是一个更可读、更可靠、更强大的解决方案。


枚举类型是其字段由一组固定常量组成的类型。常见的例子包括指南针方向(北、南、东和西的值)和星期几。

1
2
3
4
public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY
}

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

下面是一些代码,演示如何使用上面定义的day枚举:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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();
    }
}

输出是:

Mondays are bad. Midweek days are so-so. Fridays are
better. Weekends are best. Weekends are best.

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

1
2
3
4
for (Planet p : Planet.values()) {
    System.out.printf("Your weight on %s is %f%n",
                      p, p.surfaceWeight(mass));
}

除了其属性和构造,Planet还有一些方法可以让您检索每个行星上物体的表面重力和重量。下面是一个样本程序,它可以计算你在地球上的重量(以任何单位表示),并计算和打印你在所有行星上的重量(以相同单位表示):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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));
    }
}

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

$ java Planet 175 Your weight on MERCURY is 66.107583 Your
weight on VENUS is 158.374842 Your weight on EARTH is
175.000000 Your weight on MARS is 66.279007 Your weight on JUPITER is 442.847567 Your weight on SATURN is 186.552719 Your
weight on URANUS is 158.397260 Your weight on NEPTUNE is
199.207413

来源:http://docs.oracle.com/javase/tutorial/java/javaoo/enum.html


枚举是安全类型,因此不能在运行时分配新值。此外,还可以在switch语句中使用它(比如int)。


Java编程语言enums比其他语言中的其他语言要强大得多,它们只不过是美化了的整数。新的枚举声明定义了一个完整的类(称为枚举类型)。除了解决所有问题(EDOCX1,1),还存在着在Java 5之前使用的以下int模式:

public static final int SEASON_WINTER = 0;

它还允许您向枚举类型添加任意方法和字段,实现任意接口等等。枚举类型提供所有对象方法的高质量实现。它们是ComparableSerializable,串行形式设计为能够承受枚举类型的任意更改。您也可以在switch案例中使用enum。

阅读关于Java枚举HTTP://DOCS.Oracle .COM/JavaSe/1.5.0/DOCS/GuID/Laule/No.StHTML的完整文章以获取更多细节。


枚举是为一组已定义的容器(也可以有一些有限的行为)提供易于记忆的名称的推荐方法。

在使用多个静态整型常量(如public static int ROLE_ADMIN = 0BLOOD_TYPE_AB = 2时,应使用枚举。

使用枚举而不是这些枚举的主要优点是类型安全、在尝试使用错误值时编译类型警告/错误以及为相关的"常量"提供命名空间。此外,它们更容易在IDE中使用,因为它也有助于代码完成。


1)枚举是面向对象方法中的关键字。

2)它是用来把代码写在一行中的,也就是说不超过这一行。

1
2
3
4
5
6
7
8
9
10
     public class NAME
     {
        public static final String THUNNE ="";
        public static final String SHAATA ="";
        public static final String THULLU ="";
     }

-------This can be replaced by--------

  enum NAME{THUNNE, SHAATA, THULLU}

3)大多数开发人员不使用枚举关键字,它只是一种替代方法。