引入
编写季节类(Season),该类只有四个对象(spring,summer,autumn,winter)
//季节类 public class Season { 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("冬天","银装素裹"); private String name; private String info; private Season() { } private Season(String name, String info){ this.name = name; this.info = info; } public static Season getSpring() { return spring; } public static Season getSummer() { return summer; } public static Season getAutumn() { return autumn; } public static Season getWinter() { return winter; } @Override public String toString() { return "Season [name=" + name + ", info=" + info + "]"; } } public static void main(String[] args) { /** * 枚举引入: * 编写季节类(Season),该类只有四个对象(spring,summer,autumn,winter) */ System.out.println(Season.spring);//Season [name=春天, info=万物复苏] System.out.println(Season.summer); System.out.println(Season.autumn); System.out.println(Season.winter); }
概念
枚举(enum)全称为 enumeration, 是 JDK 1.5 中引入的新特性。
语法
public enum Color { //枚举中没有定义方法时,可以在最后一个对象后面加逗号、分号或什么都不加 // RED,YELLOW,GREEN // RED,YELLOW,GREEN, RED,YELLOW,GREEN; //若定义了方法,则最后一个对象后面必须加上分号 }
本质
尽管枚举看起来像是一种新的数据类型,实际上,枚举就是一种受限制的类,并且具有自己的方法。创建自己的enum类时,这个类继承自 java.lang.Enum。
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable{ ... }
特点
- 枚举就是一个受限制的类,默认继承Enum
- 枚举的第一行必须定义该枚举类型的对象
- 枚举类型对象默认添加: public static final 类型
- 枚举没有继承明确类(自定义枚举类默认继承Enum,Enum默认继承Object)
- 枚举类不能被继承
- 枚举里可以有构造方法、成员方法、静态方法、抽象方法(通过匿名内部类实现)
- 枚举可以实现接口
- 枚举里没有定义方法,可以在最后一个对象后面加逗号、分号或什么都不加
优势
增强代码可读性
枚举型可直接与数据库交互
switch语句优势
编译优势
(枚举类编译时,没有把常量值编译到代码中,即使常量值发生改变,也不会影响引用常量的类 )
将常量组织起来,统一管理
去除equals两者判断 由于常量值地址唯一,使用枚举可以直接通过“==”进行两个值之间的对比,性能会有所提高
枚举的常用方法
方法名 | 解释 |
---|---|
Enum.valueOf(Class enumType, String name) | 根据字符串找到该枚举类中的对象 |
public static void values() | 获取该枚举类对象数组 |
public static void valueOf(String args0) | 根据字符串获取该枚举类中的对象 |
public final String name() | 获取该枚举对象名字 |
public final Class getDeclaringClass() | 获取枚举对象的枚举类型相对应的Class对象 |
public final int hashCode() | 获取该枚举对象的hash值 |
public final int compareTo(E o) | 两个枚举对象进行比较 |
public final boolean equals(Object other) | 比较两个枚举对象是否相同 |
//底层实现:public class Season extends Enum public enum Season { //默认添加:public static final Season spring("春天","万物复苏"), summer("夏天","烈日灼心"), autumn("秋天","秋高气爽"), winter("冬天","银装素裹"); private String name; private String info; private Season() { } private Season(String name, String info) { this.name = name; this.info = info; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString(){ return name + "---" + info; } } //枚举的常用方法 public static void main(String[] args) { //通过字符串获取枚举的对象 Season season1 = Enum.valueOf(Season.class, "spring"); System.out.println(season1); //获取Season枚举类中所有对象 Season[] values = Season.values(); for (Season season : values) { System.out.println(season); } //通过字符串获取枚举的对象 Season season2 = Season.valueOf("winter"); System.out.println(season2); //获取枚举对象的名字 String name = season2.name(); System.out.println(name); //获取Season枚举类的字节码文件对象 Class<Season> c = season2.getDeclaringClass(); System.out.println(c); }
枚举案例
状态机
enum Signal{RED, YELLOW, GREEN} public class EnumTest { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入信号灯:RED,YELLOW,GREEN"); Signal signal = Signal.valueOf(scan.next()); String instruct = getTrafficInstruct(signal); System.out.println(instruct); scan.close(); } public static String getTrafficInstruct(Signal signal) { String instruct = "信号灯故障"; switch (signal) { case RED: instruct = "红灯停"; break; case YELLOW: instruct = "黄灯请注意"; break; case GREEN: instruct = "绿灯行"; break; default: break; } return instruct; } }
错误码
public enum ErrorCodeEn { Ok(1,"成功"),ERROR_A(2,"错误A"),ERROR_B(3,"错误B"); private int code;//状态码 private String description;//状态信息 ErrorCodeEn(){} ErrorCodeEn(int code,String description){ this.code = code; this.description = description; } public int getCode() { return code; } public String getDescription() { return description; } }
组织枚举
含义:使用类或者接口把众多的枚举组织起来
经验:一般使用接口组织
原因:
Java接口在编译时会自动为enum类型加上public static修饰符
Java类在编译时会自动为 enum 类型加上static修饰符
即在类组织中,如果不主动为enum加上public,那么就只能在本包中运行
public interface IErrorCode { enum LoginErrorCodeEn implements INumberEnum{ OK(1,"登录成功"),ERROR_A(-1,"验证码错误"),ERROR_B(-2,"密码错误"),ERROR_C(-3,"用户已登录"); private int code; private String description; LoginErrorCodeEn(int code,String description){ this.code = code; this.description = description; } @Override public int getCode() { return code; } @Override public String getDescription() { return description; } } enum RigsterErrorCodeEn implements INumberEnum{ OK(1,"注册成功"),ERROR_A(-1,"账号已存在"); private int code; private String description; RigsterErrorCodeEn(int code,String description){ this.code = code; this.description = description; } @Override public int getCode() { return code; } @Override public String getDescription() { return description; } } } interface INumberEnum { int getCode(); String getDescription(); }
策略枚举
优点:这种枚举通过枚举嵌套枚举的方式,将枚举常量分类处理。
这种做法虽然没有switch语句简洁,但是更加安全、灵活。
public static void main(String[] args) { /** * 枚举案例:策略枚举 * * 需求:计算学校所有员工的工资 * 分析: * 员工分类:行政人员、教师 * 行政人员:基本工资 + 绩效 * 教师:基本工资 + 课时费*课时 + 绩效 */ double salary1 = Salary.java.getSalary(1800, 88, 15, 400); System.out.println(salary1); double salary2 = Salary.principal.getSalary(20000, 0, 0, 20000); System.out.println(salary2); double salary3 = Salary.reception.getSalary(1200, 0, 0, 200); System.out.println(salary3); } enum Salary{ java(StaffType.teacher),//java部门 python(StaffType.teacher), principal(StaffType.administrative),//总经办(校长)部门 reception(StaffType.administrative);//前台部门 private StaffType staffType; private Salary(StaffType staffType) { this.staffType = staffType; } public double getSalary(double baseSalary, int classHour, double teachingHourSubsidy, double achievements){ return staffType.calculationSalary(baseSalary, classHour, teachingHourSubsidy, achievements); } enum StaffType{ //匿名内部类对象 administrative{//行政人员 @Override public double calculationSalary(double baseSalary,int classHour,double teachingHourSubsidy,double achievements){ BigDecimal bigBaseSalary = new BigDecimal(String.valueOf(baseSalary)); BigDecimal bigAchievements = new BigDecimal(String.valueOf(achievements)); BigDecimal bigDecimal = bigBaseSalary.add(bigAchievements); return bigDecimal.doubleValue(); } }, teacher{ @Override public double calculationSalary(double baseSalary,int classHour,double teachingHourSubsidy,double achievements){ BigDecimal bigBaseSalary = new BigDecimal(String.valueOf(baseSalary)); BigDecimal bigClassHour = new BigDecimal(classHour); BigDecimal bigTeachingHourSubsidy = new BigDecimal(teachingHourSubsidy); BigDecimal bigAchievements = new BigDecimal(String.valueOf(achievements)); BigDecimal bigDecimal =bigClassHour.multiply(bigTeachingHourSubsidy).add(bigBaseSalary).add(bigAchievements); return bigDecimal.doubleValue(); } }; //计算工资 public abstract double calculationSalary(double baseSalary,int classHour,double teachingHourSubsidy,double achievements); } }