0.枚举知识体系
1.枚举类定义
枚举类:类的对象个数有限且内容固定,如季节,只能有4个对象;性别,只能2个。
2.自定义枚举类(JDK1.5之前)
(2)private 修饰构造器,对象固定,不能在外创建对象,所以构造器私有化。
(3)该类的所有实例都用public static final修饰,因为是个数是固定的,所以类的内部创建对象,外部访问到对象代表公有,不能修改,对象名定义加入命名空间,如SEASON_SUMMER。
如下代码定义一个方向枚举类:
class Direction {
//3.<span style="font-family: SimSun;">所有实例都用public static final修饰,</span>Direction类的所有对象,以内部类形式体现。
public static final Direction DIRECTION_EAST = new Direction("东","东东东");
public static final Direction DIRECTION_WEST = new Direction("西","西西西");
public static final Direction DIRECTION_SOUTH = new Direction("南","南南南");
public static final Direction DIRECTION_NORTH = new Direction("北","北北北");
//1.<span style="font-family: SimSun;">字段使用private final修饰</span>
private final String name;
private final String desc;
//方法
public String getName(){
return this.name;
}
public String getDesc(){
return this.desc;
}
//重写toString方法
public String toString(){
return "Direction[Name:"+this.name+";Desc:"+this.desc+"]";
}
//2.私有化构造器
private Direction(String name,String desc){
this.name = name;
this.desc = desc;
}
}
3.enum定义枚举类(JDK1.5后)
0)enum级别
enum与interface、class级别是一样,可看成特殊的class;与class一样,一个java源文件最多只能定义一个public访问权限的枚举类,且该源文件也必须和枚举类类名相同。
1)定义说明
(2)private final修饰枚举类的属性,并且在构造器中赋值。
(3)构造器:构造器只能使用private修饰;若枚举类显式定义了带参数构造器,则在列出枚举值时也必须传入相应参数。
如下enum关键字定义DirectionV2
enum DirectionV2{//编译生成DirectionV2.class,说明是一个类。
//首行列出4个枚举实例,以逗号分隔,分号结尾。
EAST,WEST,SOUTH,NORTH;
}
2)枚举类与普通类区别
(1)使用enum定义的枚举类默认继承java.lang.Enum,而不是Object,当然Enum也是继承自Object。Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
(2)枚举类的构造器只能使用private访问控制符。
(3)枚举类的所有实例必须在枚举类第一行中显示列出,列出的实例系统会自动添加public static final修饰。
(4)所有的枚举类都提供values方法,该方法可以遍历所有的枚举值。
(5)使用enum定义、非抽象的枚举类默认使用final修饰,枚举类不能派生子类。
3)Enum类
(2)String name():返回此枚举实例的名称,定义枚举类时列出的所有枚举值之一。
(3)int ordinal():返回枚举值在枚举类中的索引值,即在枚举类中的声明位置,第一个枚举值的索引值为零。(4)String toString():返回枚举常量的名称,与name方法相似
(5)public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name):静态方法,返回指定枚举类中指定名称的枚举值。名称必须与该枚举类中声明枚举值时所用的标识符完全匹配,不允许使用额外空白字符。(6)values():
4)其它信息
(1)JDK1.5以后switch-case中可使用枚举类对象作为表达式。case子句可以直接使用枚举值的名字,无需添加枚举类作为限定。
(2)若枚举只有一个成员,则可以作为一种单例模式的实现方法。
5)枚举类的成员
枚举类的字段是确定的,所以所有的字段应该使用private final修饰,此时就必须使用构造器对其进行赋值(当然也可以在初始化块赋值或在定义时设定默认值,但是不常用),这时就需要带参数的构造器。
(2)方法
对枚举类的字段都要通过Getter来获取,并且不能有Setter。
(3)构造器
构造器必须是私有的,一旦定义了带参构造器就要在列出枚举值时传入参数。枚举类中列出枚举值时,实际上就是调用构造器创建枚举类对象,只是没有使用new关键字,也没显式调用构造器。
enum DirectionV2{
EAST("东"),
WEST("西"),
SOUTH("南"),
NORTH("北");
private final String chName;
public String getChName(){
return this.chName;
}
private DirectionV2(String chName){
this.chName = chName;
}
}
public class DirectionTest{
public static void main(String[] args){
DirectionV2[] ds = DirectionV2.values();
for(DirectionV2 d:ds){
System.out.println(d.getChName());
}
}
}
4.枚举类的抽象方法
1)抽象方法使用实例
假设有Operation枚举类,其有2个枚举值PLUS(加)和MINUS(减),并可以进行相应运算。此时可以采用以下方法:
enum Ope{
//首行列出,逗号分隔,分号结束。
PLUS{
public double compute(double numA,double numB){
return numA + numB;
}
},
MINUS{
public double compute(double numA,double numB){
return numA - numB;
}
};
//枚举类中的抽象方法
public abstract double compute(double numA,double numB);
}
public class OpeTest{
public static void main(String[] args)
{
System.out.println(Ope.MINUS.compute(23,1.5));
}
}
2)要点说明
(2)枚举类定义抽象方法时不需要abstract把枚举类定义成抽象类,系统会自动添加abstract关键字;
(3)枚举类中显式创建了枚举值,其实是枚举类的内部类并且继承了外部的枚举类,所以在定义每个枚举值时必须为抽象方法提供实现,否则会出现如下编译错误:
OpeTest.java:4: error: Ope is abstract; cannot be instantiated。
5.实现接口的枚举类
1)枚举类实现
枚举类也可以实现一个或多个接口,也需要实现接口中的所有方法。
interface DirectionV2Desc
{
public void desc();
}
enum DirectionV2 implements DirectionV2Desc//编译生成DirectionV2.class,说明是一个类。
{
//首行列出4个枚举实例,以逗号分隔,分号结尾。
EAST,WEST,SOUTH,NORTH;
public void desc(){
System.out.println("方向的枚举类");
}
}
public class DirectionTest
{
public static void main(String[] args){
DirectionV2[] ds = DirectionV2.values();
for(DirectionV2 d:ds){
d.desc();//调用desc()方法
}
}
}
2)枚举值实现
如果每个枚举值希望调用接口方法显示不同的行为方式,可让每个枚举值分别实现该方法。
interface DirectionV2Desc
{
public void desc();
}
enum DirectionV2 implements DirectionV2Desc//编译生成DirectionV2.class,说明是一个类。
{
//首行列出4个枚举实例,以逗号分隔,分号结尾。
EAST{
public void desc(){
System.out.println("这是东方");
}
},
WEST{
public void desc(){
System.out.println("这是西方");
}
},
SOUTH{
public void desc(){
System.out.println("这是南方");
}
},
NORTH{
public void desc(){
System.out.println("这是北方");
}
};
}
public class DirectionTest
{
public static void main(String[] args){
DirectionV2[] ds = DirectionV2.values();
for(DirectionV2 d:ds){
d.desc();//调用desc()方法
}
}