为什么要有枚举?
问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,
但有人会写成int weekday=0;
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错
枚举可以让编译器在编译时就可以控制源程序中填写的非法值。
而普通变量的方式在开发阶段无法实现这一目标
用普通类如何实现枚举功能?定义一个Weekday的类来模拟枚举功能。
1, 私有构造方法。
2, 每一个元素分别用一个公有的静态成员变量表示
3, 因为枚举类的每一个变量都是一个对象并且都是常量所以定义时加上final。
4, public static final WeekdaySUN=new Weekday();
5, public static final WeekdayMON=new Weekday();
6, 这个(对象)变量是属于Weekday里的当Weekday新建一个引用变量给它赋值时,它只能赋先前定义好的常量,否则报错。
7, 并且复写toString方法。
8, 可以有若干个公有方法或抽象方法,例如,要提供的对象身上的nextDay方法(用到了本类对象自带功能(特有功能)所以不能是静态的之所以定义静态是说明这些数据是公有的而不是特有的)必须是抽象的,当定义成抽象时,这个类也就成了抽象类。我们可以直接在刚定义的元素后再加个{}并且实现抽象方法,意为它的匿名子类实现了抽象方法(如果子类不实现父类抽象方法,那么这个子类还是一个抽象类)。
public static final Weekday SUN=newWeekday()
{
publicWeekday nextDay()
{
//星期天过后是星期一
returnMON;
}
};
public abstract Weekday nextDay();采用抽象定义nextDay就将大量ifelse语句转移成了一个个独立的类。
普通类有抽象方法是他就是抽象类,枚举即使有抽象方法但只要他在本类用匿名子类实现了这抽象方法它就不是抽象的,但普通类实现枚举功能时即使复写了抽象方法却任然是,大家要注意这方面问题!
---------------------------------------------------------------------------------------------------------------------------------------------------
用枚举来定义Weekday
Weekday weekday1=Weekday.SUN;
这个对象都有什么方法呢?
获取自己的名字Weekday1.name();
获取自己的排行(从0开始)Weekday1.ordinal();还有几个就不多说了。
再来看看枚举这个类里都有什么静态方法?
发现其中有个valueOf(Stringstr)方法
Weekday.valueOf(“SUN”)//把一个串变成对应的那个枚举元素
Weekday.values().length;返回一个数组Weekday[],把枚举里的元素一个个存进这数组里
length不是一个方法是一个属性
public enum Weekday{
SUN,MON,TUE,WED,THI,FRI,SAT;(当后面还有数据(方法)时就需要加上;)
}
实现带有抽象方法的枚举:
当枚举是内部类时,前面可以加的修饰符有四个(public 保护 默认 private )
枚举是一个类,它没有构造方法,当我们定义构造方法时,这个构造方法必须是私有的
枚举类里面的成员就是这个类的实际对象
枚举只有一个成员时,就可以作为一种单例的实现方式。
需求:定义一个交通灯,交通灯有3种颜色,红绿黄
1,那么我们就可以先定义3个成员对象(枚举里的成员不是变量而是对象)
并且这些对象都是被final修饰了的静态成员
publicEnum TrafficLight
{
RED,GREEN,YELLOW;
}
2,由于我们知道每个灯亮一定时间后会有下一个灯,他们的规律是Red后是Green,
Green后是Yellow,Yellow后是Red,这样一直循环,那么就有一个方法nextLight();
如果我们本类去完成的话要写大量if,else,所以我们把它定成抽象方法让子类去覆盖(重写)它,
publicenum TrafficLinght
{
RED,GREEN,YELLOW;
publicabstract TrafficLight nextLight();
}
3,那么这个子类重写代码该在哪里写呢?我想明确表示RED就是TrafficLight它的子类的实际对象
RED{}.这样写说明他是TrafficLinght的子类来写的,子类的代码是一对大括号,子类的名字不知道
----这其实就是匿名内部类的写法,既然是他的子类那么就必须复写父类定义的抽象方法
publicenum TrafficLinght
{
RED
{
publicTrafficLight nextLight()
{
//红灯后是绿
returnGREEN;
}
},
GREEN
{
publicTrafficLight nextLight()
{
//绿灯后是黄
return GREEN;
}
},
YELLOW
{
publicTrafficLight nextLight()
{
//黄灯后是红
returnGREEN;
}
};
publicabstract TrafficLight nextLight();
}
4,并且他们都是有时间限定的,说明有一个时间变量,这时间是它本身的,所以是私有的
有一个构造方法去初始化它,这个构造方法也是私有的(枚举里的构造方法都是私有的)
privateint time;
privateTrafficLight(int time){this.time=time;}
//5,这时每个元素调用时都可以加上()表示指定哪个构造方法,同时他还是一个子类
public enum TrafficLight
{
RED(30)
{
publicTrafficLight nextLight()
{
//红灯后是绿
returnGREEN;
}
},
GREEN(40)
{
publicTrafficLight nextLight()
{
//绿灯后是黄
returnGREEN;
}
},
YELLOW(5)
{
publicTrafficLight nextLight()
{
//黄灯后是红
returnGREEN;
}
};
publicabstract TrafficLight nextLight();
privateint time;
privateTrafficLight(int time)
{
this.time=time;
}
}
import java.util.*;
class EnumTest
{
publicstatic void main(String[] args)
{
//这表示new util的一个类,并调用父类有参构造方法“()默认是无参数的”
newDate(300){}; }}