需求:定义一个Employee(员工),使用一个变量restday来表示他哪一天休息(一周的哪一天)
class Employee
{
private int restday;//一周的哪一天休息
public int getRestday()
{
return restday;
}
public void setRestday(int restday){
this.restday = restday;
}
}
//枚举的引入
class EnumDemo
{
public static void main(String[] args)
{
//创建一个employee对象,并设置哪一天休息
Employee e = new Employee();
e.setRestday(6);
int restday = e.getRestday();
if(restday == 6 || restday == 7){
System.out.println("周末休息");
}else{
System.out.println("工作日休息");
}
}
}
上述代码,setRestday中传入13时,结果为工作日休息,数据不合理。表示星期几的类型不安全。同时业务含义不明确,设置的1表示周几(周一/周日)。
解决方案:
专门用一个类来表示周一到周日,使用七个常量来表示。
//定义一个星期几的常量类
class Weekday
{
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
public static final int SUNDAY = 7;
}
此时调用代码为:
e.setRestday(Weekday.SUNDAY);
但是,因为setRestday方法中接受的数据还是int类型,我们依然可以传入-3这样的不合理数字,依然存在数据类型不安全问题。
解决方案:
把休息日使用一个对象类型来表示,并固定该休息日的值只能是周一到周日:
//定义一个星期几的常量类
class Weekday
{
private Weekday(){}//不允许外界创建对象从而造成类型不安全问题,即只能选择以下的数据传入setRestday
public static final Weekday MONDAY = new Weekday();
public static final Weekday TUESDAY = new Weekday();
public static final Weekday WEDNESDAY = new Weekday();
public static final Weekday THURSDAY = new Weekday();
public static final Weekday FRIDAY = new Weekday();
public static final Weekday SATURDAY = new Weekday();
public static final Weekday SUNDAY = new Weekday();
}
class Employee
{
private Weekday restday;//一周的哪一天休息
public Weekday getRestday()
{
return restday;
}
public void setRestday(Weekday restday){
this.restday = restday;
}
}
//枚举的引入
class EnumDemo
{
public static void main(String[] args)
{
//创建一个employee对象,并设置哪一天休息
Employee e = new Employee();
e.setRestday(Weekday.SUNDAY);
Weekday restday = e.getRestday();
if(restday == Weekday.SATURDAY || restday == Weekday.SUNDAY){
System.out.println("周末休息");
}else{
System.out.println("工作日休息");
}
}
}
此时,类型安全了,业务含义也明确了。
02
枚举
枚举是从Java5开始提供的一种新的数据类型,是一个特殊的类,就是一个固定的多个常量对象的集合。
定义格式:
[修饰符] enum 枚举类名
{
常量A,常量B,常量C;其他代码
}
//定义一个星期几的常量类
enum Weekday{
MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
class Employee
{
private Weekday restday;//一周的哪一天休息
public Weekday getRestday()
{
return restday;
}
public void setRestday(Weekday restday){
this.restday = restday;
}
}
//枚举的引入
class EnumDemo
{
public static void main(String[] args)
{
//创建一个employee对象,并设置哪一天休息
Employee e = new Employee();
e.setRestday(Weekday.WEDNESDAY);
Weekday restday = e.getRestday();
if(restday == Weekday.SATURDAY || restday == Weekday.SUNDAY){
System.out.println("周末休息");
}else{
System.out.println("工作日休息");
}
}
}
我们自定义的枚举类型,在编译(底层)都是直接继承于java.lang.Enum类的,Enum是所有枚举类的父类。
枚举类的特点:
①枚举的直接父类java.lang.Enum,但是不能显示继承或Enum;
②枚举就相当于一个类,可以定义构造方法、成员变量、普通方法和抽象方法;
③默认私有的构造方法,即使不写访问权限也是privatel(假构造器,底层没有无参数构造器)。
④每个实例分别用一个全局常量表示,枚举类的对象是固定的,实例个数有限,不能使用new关键字。
⑤枚举实例必须位于枚举体中的最开始部分,枚举实例列表的后要有分号与其他成员相分隔。
⑥枚举实例后有花括号时,该实例是枚举类的匿名内部类对象(查看编译后的class文件)。
枚举的使用:
1)枚举中都是全局公共的静态常量可以直接使用枚举类名调用;
Weekday day = Weekday.SATURDAY;
2)因为java.lang.Enum类是所有枚举类的父类,所以所有的枚举对象可以调用Enum类中的方法
String name = 枚举对象.name(); //返回枚举对象的常量名称
ordinal = 枚举对象ordinal;//返回枚举对象的序号,从0开始
String str = 枚举对象.toString();//返回枚举对象的常量名称
3)编译器生成的枚举类的静态方法(从反编译代码中可以看到这两个方法):
枚举类型[] values();
Weekday[] ws = Weekday.values();//返回当前枚举类型所有的常量使用一个数组封装起来.
枚举类型valueof(String name);
Weekday day = Weekday.valueOf("MONDAY')://把一个指定名称字符串转换为当前枚举类中同名的常量。
4)从java5开始出现枚举,switch也支持操作枚举类型。
switch只支持int类型,支持枚举是因为底层使用的枚举对象的ordinal,而ordinal的类型依然是int类型。
System.out.println(Weekday.SATURDAY);
System.out.println(Weekday.SATURDAY.name());
System.out.println(Weekday.SATURDAY.ordinal());
System.out.println(Weekday.valueOf("SATURDAY"));
Weekday[] ws = Weekday.values();
for(Weekday day : ws){
System.out.println(day);
}
switch(Weekday.SATURDAY){
case MONDAY:break;
case TUESDAY:break;
}
枚举主要用来表示事物的固定类型。
枚举的单例模式:建议使用枚举来做单例模式,很安全,即使使用反射也不能创建对象。
之前写的单例设计模式:
//单例设计模式
class ArrayUtil
{
//1)必须在该类中,自己先创建出一个对象;
private static final ArrayUtil instance = new ArrayUtil();
//2)私有化自身的构造器,防止外界通过构造器创建新的对象;
private ArrayUtil(){}
//3)向外暴露个公共的静态方法用于获取自身的对象。
public static ArrayUtil getInstance(){
return instance;
}
//排序操作
public void sort(int[] arr){
System.out.println("排序操作");
}
}
利用枚举设计单例:
enum ArrayUtil
{
INSTANCE;//枚举中只存在一个实例对象
//排序操作
public void sort(int[] arr){
System.out.println("排序操作");
}
}
//单例设计模式
class SingletonDemo
{
public static void main(String[] args)
{
System.out.println(ArrayUtil.INSTANCE == ArrayUtil.INSTANCE);
//ArrayUtil u = new ArrayUtil();
//需要排序操作
ArrayUtil.INSTANCE.sort(null);
//需要排序操作
ArrayUtil.INSTANCE.sort(null);
//需要排序操作
ArrayUtil.INSTANCE.sort(null);
//需要排序操作
ArrayUtil.INSTANCE.sort(null);
}
}
java培训班:http://www.baizhiedu.com/java2019
注释:内容来自java学途