java枚举

每日一言

Hatred will never be erased! The only thing you can do is erase the ones you hate! – Hakuryū Ren
from Magi - The Labyrinth of Magic

枚举(enum)

Java枚举是一个特殊的类,一般表示一组常量,比如一年四个季节,一年的12个月份,一个星期的7天,方向的东西南北等。

枚举通过关键字 enum 来声明:

1
2
3
enum Season{
SPRING,SUMMER,AUTUMN,WINTER;
}

这样我们可以在代码中展示更加清晰的逻辑:

1
2
3
4
5
6
7
8
public class Main {
public static void main(String[] args) {
// Create a new instance of the MyClass class
Season season = Season.SPRING;
// Print the value of the instance
System.out.println("The current season is: " + season);
}
}

枚举类的实例化

对于我们上面的例子

1
Season season = Season.SPRING;

这句话只是创建了一个针对 Season.SPRING 的引用,也就是不论我们给多少个变量赋值为 Season.SPRING 在内存中都只有一个Season.SPRING的实例,其他都是指向它的引用。

这样的化我们可能会好奇一个问题:枚举类是在什么时候被实例化的呢?

我们写一个简单的程序来验证它:

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;

Season() {
System.out.println("Creating enum constant: " + this.name());
}
}

public class Main {
public static void main(String[] args) {
System.out.println("Main method started");
}
}

输出如下:

1
Main method started

当我们没有引用任何的枚举常量时,枚举类并没有被实例化。接下来我们创建一个枚举类的引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;

Season() {
System.out.println("Creating enum constant: " + this.name());
}
}

public class Main {
public static void main(String[] args) {

// 直接使用枚举常量
Season season = Season.SPRING;
System.out.println("Main method started");
// 不需要显式使用枚举常量,就能看到构造函数的输出
}
}

输出如下:

1
2
3
4
5
Creating enum constant: SPRING
Creating enum constant: SUMMER
Creating enum constant: AUTUMN
Creating enum constant: WINTER
Main method started

所以JVM会在首次引用枚举常量时,一次为所有的枚举常量进行实例化,顺序为我们申明的顺序。枚举类中的成员变量为每个创建的实例私有,方法为所有实例共有,与普通的类并无区别。

迭代枚举元素

可以使用for循环和 values()方法来遍历枚举的每一个值。

1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) {
for(Season s : Season.values()){
System.out.println(s);
}
}
}

枚举类型的 values() 方法是Java枚举类型自动提供的一个静态方法。当你定义一个枚举类型时,Java编译器会自动为该枚举类型生成 values()方法。

功能

这个方法会返回一个包含所有枚举常量的数组,数组中的元素按照它们在枚举声明中的顺序排序。

对于上面的例子来说,Season.values()会返回一个枚举常量数组:

1
[Season.SPRING,Season.SUMMER,Season.AUTOMN,Season.WINTER]

在switch中使用枚举类

枚举类常应用于 switch 语句中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
public static void main(String[] args) {
Season season = Season.SPRING;
switch (season) {
case SPRING:
System.out.println("Spring is here!");
break;
case SUMMER:
System.out.println("Summer is here!");
break;
case AUTUMN:
System.out.println("Autumn is here!");
break;
case WINTER:
System.out.println("Winter is here!");
break;
}
}
}

values(),ordinal(),valueOf()方法

enum 定义的枚举类默认继承了 java.lang.Enum() 类,这个类中包含了三种默认的方法:

  • values():返回枚举类中的值,返回为一个数组
  • ordinal():方法可以找到每个枚举常量的索引,就像数组的索引一样,顺序与声明顺序相同
  • valueOf():方法返回指定字符串值的枚举常量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) {
Season[] seasons = Season.values();

for (Season season : seasons) {
System.out.println(season);
System.out.println("The ordinal of SPRING is: " + season.ordinal());
}

Season tmp = Season.valueOf("SPRING");
Season tmp1 = Season.SPRING;

}
}

输出:

1
2
3
4
5
6
7
8
SPRING
The ordinal of SPRING is: 0
SUMMER
The ordinal of SPRING is: 1
AUTUMN
The ordinal of SPRING is: 2
WINTER
The ordinal of SPRING is: 3

Season.valueOf("SPRING")方法返回的枚举常量与直接使用 Season.SPRING 创建的枚举常量完全相同,它们的不同之处在于获取枚举常量的过程不同

Season.valueOf(SPRING)

  • 这是一个 方法调用 ,通过字符串参数来获取对应的枚举常量
  • 参数必须是字符串形式的枚举常量名称,且必须与枚举常量的名称完全匹配(包括大小写)
  • 如果字符串参数不匹配任何枚举常量名称,会抛出 IllegalArgumentException 异常
  • 适用于在运行时动态获取枚举常量,例如从配置文件或用户输入中读取字符串后转换为枚举

Season.SPRING

  • 这是直接引用枚举常量
  • 编译时就确定了引用的是哪个枚举常量
  • 不会抛出异常(编译时检查)
  • 代码更简洁,性能更好(不需要方法调用和异常处理)
  • 适用于在编译时已知需要使用哪个枚举常量的情况

枚举类成员

枚举跟普通类一样可以有自己的变量,方法和构造函数,但是构造函数只能使用private访问修饰符,所以外部无法调用。构造函数用于给枚举赋初值。

1
2
3
4
5
6
7
8
9
10
public enum Color{
RED(255,0,0);
private int r,g,b;
private Color(int r, int g, int b)
{
this.r = r;
this.g = g;
this.b = b;
}
}

枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

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
public enum Operation {
ADD {
@Override
public double apply(double x, double y) {
return x + y;
}
},
SUBTRACT {
@Override
public double apply(double x, double y) {
return x - y;
}
},
MULTIPLY {
@Override
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
public double apply(double x, double y) {
if (y == 0) {
throw new ArithmeticException("Division by zero");
}
return x / y;
}
};

// 抽象方法
public abstract double apply(double x, double y);
}

枚举的实例都在类的里面申明。


java枚举
http://blog.ulna520.com/2025/03/20/java枚举_20250320_224203/
Veröffentlicht am
March 20, 2025
Urheberrechtshinweis