基本介绍
枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定对象
枚举的两种实现方式
- 自定义类实现枚举
- 使用 enum 关键字实现枚举
自定义类实现枚举
- 构造器私有化,防止外部直接 new
- 去掉 set 方法,只保留 get 方法,即属性是只读的,不能修改,因为枚举对象值通常为只读
- 在类内部直接创建固定的对象
- 对枚举对象/ 属性使用 final + static 共同修饰,实现底层优化
- 枚举对象名通常全部大写(常量命名规范)
- 枚举对象根据需求可以有多个属性
以下代码完成一个需求:创建一个 Season 类,里面只包含四季和它们的描述,
public class Test {
public static void main(String[] args) {
System.out.println(Season.SUMMER);
}
}
class Season {
private String name; // 季节
private String desc; // 季节描述
// 3、在类内部创建固定的对象
// public 是为了让外部访问, static 是为了可以直接通过类名访问而不用创建对象
// 优化:可以加入 final 关键字,这样访问静态属性时不会导致类加载
// 定义了春夏秋冬四个对象
public static final Season SPRING = new Season("春天", "温暖");
public static final Season SUMMER = new Season("夏天", "炎热");
public static final Season AUTUMN = new Season("秋天", "凉爽");
public static final Season WINTER = new Season("冬天", "寒冷");
// 1、构造器私有化
private Season(String name,String desc){
this.name = name;
this.desc = desc;
}
// 2、只保留 get 方法
public String getName() {
return this.name;
}
public String getDesc() {
return this.desc;
}
public String toString(){
return "Season{" + name + " , " + desc+ "}";
}
}
使用 enum 关键字实现枚举
快速入门
public class Test {
public static void main(String[] args) {
System.out.println(Season2.SUMMER);
}
}
// 使用 enum 关键字定义枚举类
enum Season2 {
// 3、定义春夏秋冬四个对象
/*
* 使用关键字 enum 代替 class
* 枚举对象(常量)定义形式:对象名(实参列表),实参列表中的参数会传递给构造器
* 如果有多个枚举对象(常量),用逗号分隔
* 使用 enum 关键字定义枚举类,需要将常量对象写在最前面,否则会报错
*/
SPRING("春天", "温暖"),
SUMMER("夏天", "炎热"),
AUTUMN("秋天", "凉爽"),
WINTER("冬天", "寒冷");
private String name; // 季节
private String desc; // 季节描述
// 1、构造器私有化
private Season2(String name,String desc){
this.name = name;
this.desc = desc;
}
// 2、只保留 get 方法
public String getName() {
return this.name;
}
public String getDesc() {
return this.desc;
}
public String toString(){
return "Season{" + name + " , " + desc+ "}";
}
}
enum 关键字实现枚举类的注意事项
- 使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类,而且所定义的枚举类是一个 final 类
- 使用 enum 关键字后,就不能再继承其他类了,因为 enum 会隐式继承 Enum 类,而 java 是单继承机制
- 枚举类和普通类一样,可以实现接口:enum 类名 implements 接口1,接口2 {}
- 传统的 public static final Season SPRING = new Season("春天", "温暖"); 简化成 SPRING("春天", "温暖"), 这里必须知道它调用的是哪个构造器
- 如果使用无参构造器创建枚举对象,则实参列表和小括号可以省略
- 当有多个枚举对象时,使用逗号分隔,最后一个枚举对象以分号结尾
- 枚举对象必须放在枚举类的行首
Enum 类常用方法
使用关键字 enum 实现枚举类时会隐式的继承 Enum 类,这样可以使用 Enum 类相关的方法。 Enum 源码定义如下:
public abstract class Enum <E extends Enum<E>> implements Comparable<E>,Serializable {
}
- toString:Enum 类里的 toString 方法已经重写了,返回的是当前对象名,子类可以重写该方法,用于返回对象的属性信息
- name:返回当前对象名(常量名),子类中不能重写
- ordinal:返回当前对象的位置号,默认从0开始
- values:返回当前枚举类中所有的常量(源码中看不到该方法,因为被隐藏了)
- valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
- compareTo:比较两个枚举常量,比较的就是位置号
Season2 类同上
public class Test {
public static void main(String[] args) {
Season2 spring = Season2.SPRING;
// name:返回当前对象名(常量名),子类中不能重写
System.out.println(spring.name()); // SPRING
// ordinal:返回当前对象的位置号,默认从0开始
System.out.println(spring.ordinal()); // 0
// values:返回当前枚举类中所有的常量(源码中看不到该方法,因为被隐藏了)
Season2[] arr = Season2.values();
for(Season2 sea : arr){
// Season{春天 , 温暖}
// Season{夏天 , 炎热}
// Season{秋天 , 凉爽}
// Season{冬天 , 寒冷}
System.out.println(sea);
}
// valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
// 执行过程:根据传入的字符串在 Season2 类中查找有没有和字符串对应的枚举对象
// 有则返回,否则报错
Season2 spring1 = Season2.valueOf("SPRING");
System.out.println(spring1); // Season{春天 , 温暖}
// spring 和 spring1 是同一个对象
System.out.println(spring == spring1); // true
// compareTo:比较两个枚举常量,比较的就是位置号(ordinal)
/*
// compareTo 源码
public final int compareTo(E o){
Enum<?> other = (Enum<?>)o;
Enum<?> self = this;
if (self.getClass() != other.getClass() &&
self.getDeclaringClass() != other.getDeclaringClass()) {
throw new ClassCastException();
}
return self.ordinal - other.ordinal;
}
*/
// Season2.WINTER 的编号【3】 - Season2.SUMMER 的编号【1】
System.out.println(Season2.WINTER.compareTo(Season2.SUMMER)); // 2
// Season2.SUMMER 的编号【1】 - Season2.SPRING 的编号【0】
System.out.println(Season2.SUMMER.compareTo(spring)); // 1
// Season2.SPRING 的编号【0】 - Season2.SPRING 的编号【0】
System.out.println(Season2.SPRING.compareTo(spring)); // 0
}
}