每日一言
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 来声明:
enum Season{
SPRING,SUMMER,AUTUMN,WINTER;
}
这样我们可以在代码中展示更加清晰的逻辑:
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);
}
}
枚举类的实例化
对于我们上面的例子
Season season = Season.SPRING;
这句话只是创建了一个针对 Season.SPRING 的引用,也就是不论我们给多少个变量赋值为 Season.SPRING 在内存中都只有一个Season.SPRING的实例,其他都是指向它的引用。
这样的化我们可能会好奇一个问题:枚举类是在什么时候被实例化的呢?
我们写一个简单的程序来验证它:
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");
}
}
输出如下:
Main method started
当我们没有引用任何的枚举常量时,枚举类并没有被实例化。接下来我们创建一个枚举类的引用:
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");
// 不需要显式使用枚举常量,就能看到构造函数的输出
}
}
输出如下:
Creating enum constant: SPRING
Creating enum constant: SUMMER
Creating enum constant: AUTUMN
Creating enum constant: WINTER
Main method started
所以JVM会在首次引用枚举常量时,一次为所有的枚举常量进行实例化,顺序为我们申明的顺序。枚举类中的成员变量为每个创建的实例私有,方法为所有实例共有,与普通的类并无区别。
迭代枚举元素
可以使用for循环和 values()方法来遍历枚举的每一个值。
public class Main {
public static void main(String[] args) {
for(Season s : Season.values()){
System.out.println(s);
}
}
}
枚举类型的 values() 方法是Java枚举类型自动提供的一个静态方法。当你定义一个枚举类型时,Java编译器会自动为该枚举类型生成 values()方法。
功能
这个方法会返回一个包含所有枚举常量的数组,数组中的元素按照它们在枚举声明中的顺序排序。
对于上面的例子来说,Season.values()会返回一个枚举常量数组:
[Season.SPRING,Season.SUMMER,Season.AUTOMN,Season.WINTER]
在switch中使用枚举类
枚举类常应用于 switch 语句中:
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():方法返回指定字符串值的枚举常量
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;
}
}
输出:
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访问修饰符,所以外部无法调用。构造函数用于给枚举赋初值。
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;
}
}
枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。
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);
}
枚举的实例都在类的里面申明。