枚举enum
1、枚举类型:Java SE5引入了枚举类型,使用enum关键字,用于处理程序中稳定的数据集;
2、枚举的创建:枚举量为常量,所以命名时要使用大写命名;
public enum Color {
RED,YELLOW,GREEN,BLUE;
}
3、使用枚举
Color red = Color.RED;
System.out.println(red.toString()); //Output: RED
int | compareTo(E o) 比较此枚举与指定对象的顺序。 | |
boolean | equals(Object other) 当指定对象等于此枚举常量时,返回 true。 | |
protected void | finalize() 枚举类不能有 finalize 方法。 | |
String | name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。 | |
int | ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 | |
String | toString() 返回枚举常量的名称,它包含在声明中。 | |
static
| valueOf(Class<T> enumType, String name) |
遍历枚举量:
for(Color color : Color.values( )){
system.out.println(color+" "+ color.ordinal());
}
enum的枚举量本身就是常量,很适合在switch中使用,作为选项;:
public class test{
Color color;
public test(Color color){
this.color = color;}
public void descirble(){
switch(color){
case RED: System.out.println(...);break;
case YELLOW: .......
case GREEN:.........
}
}
}
静态导入和在枚举中的使用
1、静态导入:
import static,将某个类中的常量导入,在该类中可以直接使用该常量;
class Student{
static String name = "assad";
static int id = "233333";
.......
}
import static Student.name;
import static Student.id; // import Student.*;
calss Test{
main(){ println(name+id)}; //在没有静态导入时:println(Student.name+Student.id);
}
2、枚举的静态导入
enum Color{ RED,YELLOW,GREEN }
import static Color.*;
class Test{
main(){ Color red = RED; } //没有静态导入时:Color red = Color.RED;
}
使用接口组织枚举
1、所有的enum都继承自
java.lang.Enum类,由于Java不允许多重继承,
因此enum不可再继承其他的类,而应该用继承的方式实现多态;
2、除了不能继承,基本可以把enum看成一个类,
因此也可以向enum添加方法,甚至main方法;
public enum Color{
RED("The light is red"),
YELLOW("The light is yellow"),
GREEN("The light is green"); //此处的RED、YELLOW、GREEN为枚举量,相当于Color类的实例,只不过在Color中实例是固定的;
private String description;
public Color(String description;){ this.description = description; }
public String getString(){ return description; }
public void main(String[] args){
for(Color c : Color.values())
System.out.println( c + c.getString() );
}
}
3、使用接口对一个enum中的枚举元素进行分类:
对于enum而言,实现接口是使其子类化的唯一办法;
public interface Food{
enum Appetizer implements Food {SALAD,SOUP,SPRING_ROLLS}
enum MainCourse implements Food {HUMMOUS,LASAGNE,BURRITO}
enum Dessert implements Food {FRUIT,TIRAMISU}
}
//相当于在Food接口中定义上实现该接口的内部类;
//Test
main(){
Food food1= Appetizer.SALAD;
Food food2 = MainCourse.HUMMOUS;
}
4、创建枚举的枚举,实现对枚举的分类
public enum Course{
APPETIZER(Food.Apperizer.class);
MAINCOURSE(Food.MainCourse.class);
DESSERT(Food.Dessert.class);
private Food[] values;
private Course(Class<? extends Food> kind){ values = kind.getEnumConstant() };
//T [ ] Class<T>.getEnumConstants() 获取一个类的所有枚举量;
public Food ranodmSelecion(){ return RandomEnums.random(values); }
}
//Test
main(){
for(Course cour : Course.values()){
Food food = cour.randomSelection();
System.out.println(food);
}
}//这样通过两层的enum,就可以打印出一套随机的Course组合;
使用enum实现对枚举量的随机选取
import java.util.Random;
public class RandomEnums{
private static Random rand = new Random();
public static <T extends Enum<T>> random(Class<T> enumClass){
return random(enumClass.getEnumConstants());
}
public static <T extends Enum<T>> random(T[ ] values){
return values[rand.nextInt(values.length)];
}
}
//Test:
main(){
Color randomColor = RandomEnums.random(Color.class);
Color randomColor2 =RandomEnums.random(Color.values());
}
使用EnumSet代替Enum
1、Java SE5引入了EnumSet,是为了通过enum创建一种替代品,替代传统基于int的“位标志”,EnumSet优点在于:
①EnumSet在说明一个二进制位是否存在时,具有更好地表达能力,而且无需当心性能;
②可以自EnumSet中添加和删除元素,但不能在Enum中删除和添加元素;
2、示例代码:
enum AlarmPoints{ A1,A2,A3,A4,B1,B2,B3 }
import static AlarmPoints.*;
main(){
EnumSet<AlarmPoints> points = EnumSet.allof(AlarmPoints.class); //创建包含AlarmPoints枚举量的EnumSet
EnumSet<AlarmPoints> p2 = EnumSet.noneof(AlarmPoints.class); //创建AlarmPoints类型的空EnumSet
EnumSet<AlarmPoints> p3 = EnumSet.of(A1,A2,B1,B2); //创建包含AlarmPoints中若干枚举量的EnumSet
p2.add(AlarmPoints.A1);
p2.add(p3)
points.removeAll(p2);
points.removeAll(EnumSet.of(A4));
}
使用EnumMap
1、EnumMap是一种特殊的Map,
它要求其所的键(key)必须来自于一个enum,由于enum本身的限制,使得EnumMap在内部可以有数组组成,
因此EnumMap的速度很快;
2、EnumMap的创建,其他操作和一般的Map一样;
EnumMap<K,V> map = new EnumMap<K,V>(class<K> keytype);
EnumMap<K,V> map = new EnumMap<K<V>(EnumMap<? extends K,V> m); //使用一个EnumMap创建,同时具有m的所有映射;
示例:
EnumMap<Color,Inetegr> m1 = new EnumMap<Color,Integer>(Color.class);
EnumMap<Color,Integer> m2 = new EnumMap<Color,Integer>(m1);
常量相关方法
1、J
ava的enum允许程序员为enum实例编写方法,从而为每个enum实例赋予各自不同的行为;
要实现常量方法,要先为enum定义一个abstract方法,然后为每一个enum实现该抽象方法;
public enum SpecificMethod{
DATE{
String geInfo(){ return DateFormat.getDateInstance().format(new Date()); }
}
CLASSPATH{
String getInfo(){ return System.getenv("CLASSPATH"); }
}
VERSION{
String getInfo(){ return System.getProperty("java.version"); }
}
abstract String getInfo();
}
//通过调用不同枚举实例的getInfo方法,体现出enum多态的行为;
//Test
main(){
for(SpecificMethod method : SpecificMethod.values())
System.out.println(method.getInfo());
}
※与直接使用匿名内部类相比,定义常量方法语法更加高效,简洁;
2、除了实现abstratc方法以外,也可以请将其作为普通方法实现
,同时在枚举常量内部对其进行覆盖;
public enum Points{
A1,A2,A5,
A3{
String description(){ return "VIP room" ;}
}
A4{
String description(){ return "bathroom"; }
}
String description(){ return "room"};
}
19.8 多路分发
1、Java支持单路分发,如果要执行的操作包含了不止一个类型未知的对象时,Java的动态绑定机制只能处理其中的一个类型;
2、实现两路分发的思路:要有两个方法调用,第一个方法调用决定第一个未知类型,第二个方法调用决定第二个未知类型;
public enum OutCome { WIN,LOSE,DRAW }
public interface Item {
OutCome compete(Item it);
OutCome eval(Paper p);
OutCome eval(Scissors s);
OutCome eval(Rock r);
}
public class Paper implements Item{
public OutCome compete(Item it){ return it.eval(this);}
public OutCome eval(Paper p){ return DRAW;}
public OutCome eval(Scissors s){ return LOSE; }
public OutCome eval(Rock r){ return WIN;}
public String toString(){ return "Paper"; }
}
public class Scissors implements Item{
public OutCome compete(Item it){ return it.eval(this); }
public OutCome eval(Paper p){ return WIN; }
public OutCome eval(Scissors s){ return DRAW;}
public OutCome eval(Rock r){ return LOSE; }
public String toString(){ return "Scissors"; }
}
public class Rock implements Item{
public OutCome compete(Item it){ return it.eval(this);}
public OutCome eval(Paper p){ return LOSE; }
public OutCome eval(Scissors s){ return WIN; }
public OutCome eval(Rock r){ return DRAW; }
public String toString(){ return "Rock"; }
}
public class RoShamBo {
static final int SIZE = 20;
private static Random rand = new Random();
public static Item newItem(){
switch(rand.nextInt(3)){
default:
case 0: return new Paper();
case 1: return new Scissors();
case 2: return new Rock();
}
}
public static void match(Item a,Item b){
System.out.println(a+" VS "+b+" : "+a.compete(b));
}
public static void main(String[] args){
for(int i=0;i<SIZE;i++){
match(newItem(),newItem());
}
}
}