一、枚举的概念:
枚举类型(Enumeration)是一种数据类型,允许程序员为一组相关的常量,这使得代码更利于理解和维护
枚举的基本概念包括以下几个核心点:
-
类型安全
枚举提高了代码的类型安全,因为枚举变量只能被赋予那些被明确声明的值。这防止了数据赋值错误,比如将不相关的整数或字符串赋值给需要特定枚举值的变量 。
2.命令常量
枚举提供了一种方式来命名一组整数值,使得代码更加清晰和易于理解。例如,代替数字表示星期的不同日子,使用枚举可以明确地使用
Day.Monday
、Day.Tuesday
等。
3.更好组织
使用枚举可以将一组固定的相关集中管理,这样做有助于组织代码,并减少维护成本,列如:你可以创建一个枚举来表示订单的各种状态(如已提交、正在处理、已完成等)。
4.自动赋值
在大多数编程语言中,枚举的每个成员默认会被赋予一个整数值,通常从 0 开始。也可以显式地为枚举成员赋值。这样,枚举成员既可以通过其名字也可以通过其整数值来引用。
二、枚举的演变
统计学生分数,并且评判等级,A级、B级、C级
1.0数据合法性验证–正则
一.封装学生类
package HomeWrok;
/**
* @author 程序梦
* @ClassName
* @Description
* @Annotation
* @date 2024/4/29
**/
public class Student {
private String name;
private String grade;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return grade;
}
public void setGrade(String grade) {
// 使用正则表达式限制等级只能是这些
if(!grade.matches("[ABCDE]")) {
throw new RuntimeException("等级只能是A B C D E") ;
}
this.grade = grade;
}
@Override
public String toString() {
return "姓名:" + this.name + ",等级:" + this.grade;
}
}
二、测试结果
1.错误结果:
package HomeWrok;
/**
* @author 程序梦
* @ClassName
* @Description
* @Annotation
* @date 2024/4/29
**/
public class MainEeum {
public static void main(String[] args) {
Student student = new Student();
// 抛出等级只能是A B C D E
student.setGrade("1");
}
}
结果截图:
2.正确结果:
package HomeWrok;
/**
* @author 程序梦
* @ClassName
* @Description
* @Annotation
* @date 2024/4/29
**/
public class MainEeum {
public static void main(String[] args) {
Student student = new Student();
// 抛出等级只能是A B C D E
student.setName("苏粥粥");
student.setGrade("A");
System.out.println(student);
}
}
结果截图:
2.0 改进,对象实现
把等级封装成一个类
第一:封装等级
public class Grade {
private String value ;
// 私有化构造方法,不允许在类外实例化对象
private Grade() {}
private Grade(String value) {
this.value = value ;
}
// 实现化五个对象
public static final Grade A = new Grade("优秀");
public static final Grade B = new Grade("良好");
public static final Grade C = new Grade("中等");
public static final Grade D = new Grade("合格");
public static final Grade E = new Grade("不合格");
@Override
public String toString() {
return this.value;
}
}
第二:重新封装学生对象,引用Grade对象
class Student {
// 姓名
private String name ;
// 等级:必须只能是 A B C D E 五种级别 将等级类当做学生的属性
private Grade grade ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
@Override
public String toString() {
return "姓名:"+this.name + ",等级:"+this.grade;
}
}
第三:测试
class MainTest {
public static void main(String[] args) {
Student stu = new Student() ;
stu.setName("张三");
stu.setGrade(Grade.B);
System.out.println(stu);
}
}
截图展示
使用枚举类改进
1.创建枚举类
// 定义枚举类
public enum Grade {
// 枚举类的值,也可以说是枚举类的实例
A("优秀"),B("良好"),C("及格"),D("差"),E("非常差");
// 定义属性:表示等级ABCDE对应的中文表示
private String value ;
// 定义构造方法
private Grade(String value) {
this.value = value ;
}
// 重写 toString 方法
@Override
public String toString() {
return this.value;
}
}
需注意如果想给枚举类的值加上中文提示必须定义构造方法和属性不然会报错因为每一个值都是枚举类的实例.
2.测试
public static void main(String[] args) {
Student student = new Student();
student.setName("粥粥");
student.setGrade(Grade.A);
System.out.println(student);
}
3.效果截图
1.改进Grade枚举—指定A、B、C、D、E五个等级的分数范围
public enum Grade {
/**
* 创建枚举列表值,并且使用构造方法初始化属性;
* 同时,由于枚举类中定义了抽象方法,不能直接创建枚举值,
* 因此,创建枚举值时,必须以匿名内部类方式创建
* 而且在匿名内部类中重写方法,实现返回该等级对应的分数范围
*/
A("优秀") {
@Override
public String getScoreRange() {
return "90-100";
}
}, B("中等") {
@Override
public String getScoreRange() {
return "80-89";
}
}, C("良") {
@Override
public String getScoreRange() {
return "79-60";
}
}, D("差") {
@Override
public String getScoreRange() {
return "0-59";
}
};
private String value;
/**
* 构造方法来赋值
*
* @param value
*/
private Grade(String value) {
this.value = value;
}
/**
* 抽象方法来控制分数的范围
*/
public abstract String getScoreRange();
/**
* 定义成员方法
*/
public void sayHello() {
System.out.println("成员方法");
}
/**
* 定义静态方法
*/
public static void testStatic() {
System.out.println("静态方法");
}
}
因为每个枚举值都是枚举类的实例,所以我们直接写一个抽象方法来控制返回分数范围
2.测试
public class MainTest {
public static void main(String[] args) {
// 创建学生对象并初始化数据
Student stu = new Student();
stu.setName("粥粥");
stu.setGrade(Grade.A);
// 输出学生信息
System.out.println(stu);
// 获取学生的等级,并打印输出该等级的分数范围
Grade g = stu.getGrade();
System.out.println("分数范围:" + g.getScoreRange());
// 调用枚举成员方法
g.sayHello();
// 调用枚举静态方法
Grade.testStatic();
}
}
3.结果截图
可以看到枚举更好去设置一些不用固定的值
三、语法
[访问修饰符] enum 枚举类名 {
// 枚举常量 - 枚举实例(枚举值)
// 成员变量、常量
// 成员方法、抽象方法、静态方法、重载方法、重写方法
// 构造方法
}
重点:
- 1.枚举是特殊的类,在声明枚举类时,可以定义构造方法,成员方法,成员变量
- 枚举常量是枚举类型的实例,它们是不可变的、公共的、静态的和最终的。
- 构造方法必须私有的(默认)。
- 2.枚举实例必须要求先定义,也就说,枚举值必须定义在枚举类的第一行代码中;
- 3.规范
- 命名规范:全大写命名,多个单词间使用下划线分隔
- 注释规范:所有的枚举类型字段必须要有注释,说明每个数据项的用途
- 4.各个枚举值逗号分隔,枚举类中仅仅只有枚举值,则可以省略分号,否则必须显式写分号
- 5.不能使用泛型
// 错误
public enum Color<T> {
...
}
- 6.使用枚举常量
语法:枚举类名.枚举常量
四、要点
1、添加新的方法
public enum Color {
RED("红"),GREEN("绿"),BLUE("蓝");
private String value ;
private Color(String value) {
this.value = value ;
}
// 添加成员方法
public String getValue() {
return value;
}
}
2、重写toString方法
public enum Color {
RED("红"),GREEN("绿"),BLUE("蓝");
private String value ;
private Color(String value) {
this.value = value ;
}
// 添加成员方法
public String getValue() {
return value;
}
// 重写方法
public String toString() {
return this.value;
}
}
3、switch的支持
//1)定义枚举
public enum Color {
RED,GREEN,BLUE
}
//2)测试 -- switch对枚举的支持
public class MainTest {
public static void main(String[] args) {
Color week = Color.RED;
switch(week) {
case RED:
System.out.println("红");break;
case GREEN:
System.out.println("绿");break;
case BLUE:
System.out.println("蓝");break;
}
}
}
结果截图:
4、Enum常用方法
枚举类型都隐式继承了java.lang.Enum类,因此不能继承其他类,但可以实现接口。
Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。
1)name()
返回枚举常量的名称,正是因为在其枚举声明中声明。
Color color = Color.RED;
String name = color.name();
System.out.println(name);
结果截图:
2)valueOf(String name)
根据枚举常量名称,返回枚举的常量(也可以理解返回成员属性)
Color color = Color.valueOf("RED");
System.out.println(color.getValue());
结果截图
3)values()
遍历枚举类所有的枚举值
Color[] colors = Color.values();
for (Color color : colors) {
System.out.println(color.name());
}
结果截图
注意:神秘的values()方法和valueOf(String)方法,这两个方法在其父类Enum中并不存在,那么它们哪里来的呢?答案是:它们是在创建枚举实例时,由编译器添加的static方法。
4)valueOf(Class enumType, String name)
此方法返回具有指定名称的指定枚举类型的枚举常量
Color color = Enum.valueOf(Color.class,"RED");
System.out.println(color.getValue());
结果截图
区别valueOf(String name)与valueOf(Class enumType, String name)。前者是编译器添加的静态方法,后者是继承自Enum类的静态方法。
5)ordinal()
返回此枚举常量的序数(其枚举声明中的位置,其中初始常量被分配一个序号零)
Color color = Color.RED;
int ordinal = color.ordinal();
System.out.println(ordinal);
结果截图
6)compareTo()
比较两个枚举值常量序数之差
Color color = Color.RED;
int n = color.compareTo(Color.BLUE) ; //0 减 2
System.out.println(n);
结果截图
五、应用案例
public enum ResponseCode {
SUCCESS(200,"成功"),
ILLEGAL_ARGUMENT(401,"无效参数"),
NEED_LOGIN(403,"权限不够"),
ERROR(500,"服务器错误");
private final int code;
private final String desc;
ResponseCode(int code,String desc){
this.code = code;
this.desc = desc;
}
public int getCode(){
return code;
}
public String getDesc(){
return desc;
}
}
在实际开发中,我们可以使用枚举来写我们的响应编码