1.1命名常量
1.2命名常量组
可以把一组相关的常量封装到一个类中。
final和static的顺序是可换的,但是最好保持一致的代码风格。因为字段是static的,所以可以直接用类名来访问常量字段。
class Suit {
final static int CLUBS = 1;
final static int DIAMONDS = 2;
final static int HEARTS = 3;
final static int SPADES = 4;
}
1.3 枚举类型
可以把上述的Suit改写为一个枚举类:
enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }
每个枚举类的字段都是被static final隐式修饰。
下面来详细探讨Java中的枚举类型(Enumeration)
Enum对象是无法用new生成的,Enum对象就是static的,无须new,直接使用。
Enum对象的值只能是null和它所定义的值,比如,Suit对象只能是null或它定义的四个值。
Suit test = null ;
test = Suit.CLUBS ;
枚举类型的声明
枚举是特殊的类型,它的声明格式也有所不同:
(1) 关键字使用enum而非class。
(2) 枚举常量字段出现在最前的声明处。如果有其他的字段、方法(包括初始化块)必须写在枚举常量字段后面。而枚举常量字段必须使用分号作为结束标记。
(3) 允许最后一个常量字段后跟随一个逗号,但是还有其他成员的话,最后一个常量字段后必须跟上分号(如果要写了逗号的话,分号在逗号后面)。
enum Suit {
CLUBS,
DIAMONDS,
HEARTS,
SPADES, ;
public static int getSize() { return 4; }
}
枚举类型的构造本质
枚举类型的枚举常量字段是隐式的public、static和final的,这个字段的类型就是你定义的枚举类型本身。枚举常量字段前除了注解(annotations)外,不能有任何的修饰符,这些修饰符都被隐藏了。
构造过程
枚举类型的枚举常量字段构造是通过调用该枚举类型的缺省的无参构造方法完成的。当然对于一个枚举类型,也可以声明任意个构造函数,只需要在枚举常量字段后附加对应的参数即可。
enum Suit {
CLUBS("CLUBS"),
DIAMONDS("DIAMONDS"),
HEARTS("HEARTS"),
SPADES("SPADES");
String name;
Suit(String name) { this.name = name; }
public String toString() { return name; }
}
枚举类型构造方法的限制:
(1) 所有构造方法的修饰符是private。如果缺省不写,默认为private
(2) 构造方法不能显式地调用父类的构造方法。因为这种调用有编译器自动完成。
(3) 构造方法不能使用枚举类型的静态字段(枚举常量字段除外) 。
特定于常量字段的行为
首先来看个例子:
enum ChessPiece {
PAWN {
Set<Position> reachable(Position current) {
return ChessRules.pawnReachable(current);
}
},
ROOK {
Set<Position> reachable(Position current) {
return ChessRules.rookReachable(current);
}
},
// ...
QUEEN {
Set<Position> reachable(Position current) {
return ChessRules.queenReachable(current);
}
};
// declare the methods defined by this enum
abstract Set<Position> reachable(Position current);
}
这个例子上显示出,每个枚举常量字段后都跟随了一个类的定义体,说明这是个匿名内部类,这个匿名内部类隐式继承了外部的的枚举类,这就是为什么不能在Enum前用final修饰符的原因了。
枚举常量字段要实现的方法必须要么是枚举类型显式声明的方法,要么是枚举类型实施的接口内的方法;此外,如果该方法被声明为abstract,则该枚举的所有常量字段都必须实现该方法,因为这个枚举常量字段此时位匿名内部枚举类,枚举类是不允许为抽象类的,如果有一个字段未重写该方法的话,这个内部类就变为了抽象类了。
枚举类型的继承特性
Enum类型不能extend任何类型(缺省地extend了java.lang.Enum类),也不能被任何其他类extend(enum行为上是final的);但是,enum可以implement任何接口,实际上任何enum类型都隐式实施了Serializable和Comparable接口。
Enum类型不能重写finalize方法。
Enum类型也不能被声明为abstract,但可以声明abstract方法。
Enum类型也不能被声明为final,即使不能显示被extend,也可能被内部类隐式extend。
Enum类型可以使用switch进行判断,而普通的对象引用是不允许这样做的。