关键词enum可以将一组具名的值的有限集合创建为一种新的类型, 而这些具名的值可以作为常规的程序组件使用, 这是一种非常有用的功能

  • 基本enum特性

enum Shrubbery {
    GROUND, CRAWLING, HANGING
}
public class EnumClass {
    public static void main(String[] args) throws Exception {

//values()方法遍历enum中所有的实例
        for(Shrubbery s : Shrubbery.values()) {

//ordinal()返回实例在enum中唯一的序号(声明时的次序)
            print(s + " oridinal: " + s.ordinal());

//enum实现了Comaparable接口, 所以具有compareTo接口
            printnb(s.compareTo(Shrubbery.CRAWLING) + " ");

//enum自动提供了equals()方法和hashCode()方法
            printnb(s.equals(Shrubbery.CRAWLING) + " ");
            print(s == Shrubbery.CRAWLING);

//获取声明的enum名
            print(s.getDeclaringClass());
            print("------------");
        }
    }
}

导入enum

这是一个enum

public enum Spiciness {
    NOT, MILD, MEDIUM, HOT, FLAMING
}

静态导入这个enum

import static enumerated.Spiciness.*;
public class Burrito {
    Spiciness degree;
    public Burrito(Spiciness degree) {
        this.degree = degree;
    }
    public String toString() {
        return "Burrito is " + degree;
    }
    public static void main(String[] args) throws Exception {
        System.out.println(new Burrito(NOT));
        System.out.println(new Burrito(HOT));
    }
}

  • 向enum中添加新方法

可以向enum中添加方法, 甚至main方法

public enum OZWitch {
    WEST("west"),
    NORTH("north"),
    EAST("east"),
    SOUTH("south");

//必须在最后一个实例的最后加一个分号
    private String description;

//添加了一个每一个实例用一个字符串描述自身的构造器
    private OZWitch(String description) {
        this.description = description;
    }
    public String getDescription() { return this.description; }
    public static void main(String[] args) {
        for(OZWitch witch : OZWitch.values()) {
            print(witch + ": " + witch.getDescription());
        }
    }
}

覆盖enum的方法

public enum SpaceShip {
    COUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP;

//覆盖toString()方法, 改变输出实例的格式
    public String toString() {

//name()返回实例的名字, 即定义时全大写的形式
        String id = name();
        String lower = id.substring(1).toLowerCase();

//返回开头大写, 后面都是小写的形式
        return id.charAt(0) + lower;
    }
    public static void main(String[] args) {
        for(SpaceShip s : values()) {
            System.out.println(s);
        }
    }
}

  • 在switch中使用enum

enum Signal { GREEN, YELLOW, RED }
public class TrafficLight {
    Signal color = Signal.RED;
    public void change() {
        switch(color) {
        case RED: color = Signal.GREEN;
        break;
        case GREEN: color = Signal.YELLOW;
        break;
        case YELLOW: color = Signal.RED;
        }
    }
}

enum中自动存储了每个实例的序号, 用switch读取enum实例的时候, 编译器会自动帮我们调用oridinal()获取它的序号值

  • values()

enum Explore { HERE, THERE }

反编译后的Explore

Compiled from "Reflection.java"
final class enumerated.Explore extends java.lang.Enum<enumerated.Explore> {
  public static final enumerated.Explore HERE;
  public static final enumerated.Explore THERE;
  static {};
  public static enumerated.Explore[] values();
  public static enumerated.Explore valueOf(java.lang.String);
}

values()方法是编译器向enum中添加的static方法, 如果你把enum实例向上转型成Enum, 就失去这个方法了

但是在Enum的Class里有一个getEnumConstants()方法, 可以获取实例

for(Enum en : e.getClass().getEnumConstants())
            System.out.println(en);

  • 实现, 而非继承

enum都继承自Enum, 所以不能再继承其他类, 只能实现接口

随机选取

下面是一个生成随机选取实例的例子

public class Enums {
    private static Random rand = new Random(47);
    public static <T extends Enum<T>> T random(Class<T> ec) {
        return random(ec.getEnumConstants());
    }
    public static <T> T random(T[] values) {
        return values[rand.nextInt(values.length)];
    }
}

<T extends Enum<T>>表示T是Enum的一个实例, 将Class<T>作为参数, 就可以获取实例的数组

重载的从实例数组随机选取的方法就跟Enum类无关了

  • 使用接口组织枚举

在一个接口的内部, 创建实现该接口的枚举, 以此将枚举分组

下面这些枚举代表不同的食物种类, 它们都实现了food接口, 可以向上转型为统一的food类型

public interface Food {
    enum Appetizer implements Food {
        SALAD, SOUP, SPRING_ROLLS
    }
    enum MainCourse implements Food {
        LASAGNE, BURRITO, PAD_THAI,
        LENTILS, HUMMOUS, VINDALOD
    }
}

可以像下面这样, 写一个枚举的枚举, 由于这些枚举都是实现了同一接口的子枚举, 可以将它们向上转型

为食物类型

public enum Course {
    APPETIZER(Food.Appetizer.class),
    MAINCOURSE(Food.MainCourse.class);
    private Food[] values;
    private Course(Class<? extends Food> kind) {
        values = kind.getEnumConstants();
    }
    public Food randomSelection() {
        return Enums.random(values);
    }
}

取出每个枚举以及它包含的实例的时候, 可以转换为food类型

for(int i = 0;i < 5;i++) {
            for(Course course : Course.values()) {
                Food food = course.randomSelection();
                System.out.println(food);
            }
            System.out.println("---");
}

或者直接把接口嵌套在一个枚举里面

public enum SecurityCategory {

//STOCK和BOND里面存储的是接口里面定义的两个枚举的实例
    STOCK(Security.Stock.class),
    BOND(Security.Bond.class);
    private Security[] values;
    SecurityCategory(Class<? extends Security> kind) {
        values = kind.getEnumConstants();
    }
    interface Security {
        enum Stock implements Security { SHORT, LONG, MARGIN }
        enum Bond implements Security { MUNICIPAL, JUNK }
    }
    public Security randomSelection() {
        return Enums.random(values);
    }
    public static void main(String[] args) {
        for(int i = 0;i < 10;i++) {
            SecurityCategory category = 
                Enums.random(SecurityCategory.class);
            System.out.println(category.randomSelection());
        }
    }
}

  • 使用EnumSet替代标志

将一种enum类型的一些实例放进EnumSet中

public class EnumSets {
    public static void main(String[] args) throws Exception {

//noneof()创建一个空的EnumSet

//初始化用enum.class
        EnumSet<AlarmPoints> points = 
            EnumSet.noneOf(AlarmPoints.class);
        points.add(BATHROOM);
        print(points);
        points.addAll(EnumSet.of(START1, START2, KITCHEN));
        print(points);

//加入整个enum
        points = EnumSet.allOf(AlarmPoints.class);
        print(points);
        points.removeAll(EnumSet.of(START1, START2, KITCHEN));
        print(points);
        points = EnumSet.complementOf(points);
    }
}

  • EnumMap

EnumMap要求其中的键必须来自一个enum,

由于enum数量的限制, 所以EnumMap内部可以由数组实现

Command用了命令模式, 是一个只有一个方法的接口

interface Command { void action(); }

public class EnumMaps {
    public static void main(String[] args) throws Exception {

//初始化也是用enum.class
        EnumMap<AlarmPoints, Command> em = 
            new EnumMap<AlarmPoints, Command>(AlarmPoints.class);
        em.put(KITCHEN, new Command() {
            public void action() {
                print("kitchen fire!");
            }
        });
        em.put(BATHROOM, new Command() {
            public void action() {
                print("Bathroom alert!");
            }
        });
        for(Map.Entry<AlarmPoints, Command> e : em.entrySet()) {
            printnb(e.getKey() + ": ");
            e.getValue().action();
        }
        try {
            em.get(UTILITY);
        } catch(Exception e) {
            print(e);
        }
    }
}

每一个enum的实例可以在内部定义一些自己的行为,

在enum中定义一个抽象方法, 然后为每个实例实现这个方法

public enum ConstantSpecificMethod {
    DATE_TIME {
        String getInfo() {
            return DateFormat.getDateInstance().format(new Date());
        }
    },
    CLASSPATH {
        String getInfo() {
            return System.getProperty("classpath");
        }
    },
    VERSION {
        String getInfo() {
            return System.getProperty("java.version");
        }
    };
    abstract String getInfo();
    public static void main(String[] args) {
        for(ConstantSpecificMethod csm : values())
            System.out.println(csm.getInfo());
    }
}

看上去实例就像是enum的子类一样, 用这种方式实现了多态, 实际上并不是

enum的实例只是enum的static final对象, 它不能访问enum中的非静态成员, 所实现的抽象方法所能实现的方法也是有限的,

这些方法只能是常量相关的

下面是一个enum反编译后的结果

abstract class enumerated.LikeClasses extends java.lang.Enum<enumerated.LikeClasses> {
  public static final enumerated.LikeClasses WINKEN;
  public static final enumerated.LikeClasses BLINKEN;
  public static final enumerated.LikeClasses NOD;
  static {};
  abstract void behavior();
  public static enumerated.LikeClasses[] values();
  public static enumerated.LikeClasses valueOf(java.lang.String);
  enumerated.LikeClasses(java.lang.String, int, enumerated.LikeClasses);
}

枚举中实例的方法, 也可以覆盖掉enum中已有的方法

使用enum职责链

职责链设计模式是为了解决一个问题, 把不同的解决方案放到一起形成一个职责链, 当有问题的请求来时, 逐一执行链上每一环, 直

到解决问题

下面是一个邮局处理信件的例子

//每一个Mail对象代表一封待解决的邮件

class Mail {

//这每一个enum代表一种对信件处理的方式, 把它们串起来就是一个职责链

//每一次尝试都可以看作一个策略, 只有当策略返回YES, OK表示解决时, 完成职责链
    enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}
    enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
    enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4}
    enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
    enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5}
    GeneralDelivery generalDelivery;
    Scannability scannability;
    Readability readability;
    Address address;
    ReturnAddress returnAddress;
    static long counter = 0;
    long id = counter++;
    public String toString() { return "Main " + id; }
    public String details() {
        return toString() + 
            ", General Delivery: " + generalDelivery + 
            ", Address Scannability: " + scannability + 
            ", Address Readability: " + readability +
            ", Address Address: " + address +
            ", Return address: " + returnAddress;
    }

//随机产生一个Mail对象, 里面为每一种enum随机分配一个实例
    public static Mail randomMail() {
        Mail m = new Mail();
        m.generalDelivery = Enums.random(GeneralDelivery.class);
        m.scannability = Enums.random(Scannability.class);
        m.readability = Enums.random(Readability.class);
        m.address = Enums.random(Address.class);
        m.returnAddress = Enums.random(ReturnAddress.class);
        return m;
    }

//Mail的迭代器, 每次迭代产生是上面的随机邮件
    public static Iterable<Mail> generator(final int count) {
        return new Iterable<Mail>() {
            int n = count;
            public Iterator<Mail> iterator() {
                return new Iterator<Mail>() {
                    public boolean hasNext() { return n-- > 0; }
                    public Mail next() { return randomMail(); }
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }
}
public class PostOffice {

//用MailHandler进行每个实例的尝试, 当有一种实例返回成功的结果, 就返回true, 表示邮件被成功解决
    enum MailHandler {
        GENERAL_DELIVERY {
            boolean handle(Mail m) {
                switch(m.generalDelivery) {
                    case YES:
                    print("Using general delivery for " + m);
                    return true;
                    default: 
                    return false;
                }
            }
        },
        MACHINE_SCAN {
            boolean handle(Mail m) {
                switch(m.scannability) {
                    case UNSCANNABLE: return false;
                    default: {
                        switch (m.address) {
                            case INCORRECT: return false;
                            default: 
                                print("Delivering " + m + " automatically");
                            return true;
                        }
                    }
                }
            }
        },
        VISUAL_INSPECTION {
            boolean handle(Mail m) {
                switch(m.readability) {
                    case ILLEGIBLE: return false;
                    default: {
                        switch (m.address) {
                            case INCORRECT: return false;
                            default: 
                                print("Delivering " + m + " normally");
                            return true;
                        }
                    }
                }
            }
        },
        RETURN_TO_SENDER {
            boolean handle(Mail m) {
                switch(m.returnAddress) {
                    case MISSING: return false;
                    default: {
                        switch (m.address) {
                            case INCORRECT: return false;
                            default: 
                                print("Returning " + m + " to sender");
                            return true;
                        }
                    }
                }
            }
        };
        abstract boolean handle(Mail m);
    }

//遍历enum MailHandler的每种尝试, 里面可以调用不同的handle方法
    static void handle(Mail m) {
        for(MailHandler handler : MailHandler.values())
            if(handler.handle(m))
                return;
        print(m + " is a dead letter");
    }

//随机产生10个Mail, 对每个Mail, 执行一次职责链
    public static void main(String[] args) throws Exception {
        for(Mail mail : Mail.generator(10)) {
            print(mail.details());
            handle(mail);
            print("********");
        }
    }
}

使用enum的状态机

下面用了一个自动售货机的例子来表示一个状态机

定义个一个输入enum, Input每个实例具有一个值, 代表钱的价值或者商品价值

//用一个enum将这些输入状态归类

enum Category {

//不同种类的钱
    MONEY(NICKEL, DIME, QUARTER, DOLLAR),

//不同种类的商品
    ITEM_SELECTION(TOOTHPASTE, CHIPS, SODA, SOAP),

//结束交易
    QUIT_TRANSACTION(ABORT_TRANSACTION),

//结束整个状态
    SHUT_DOWN(STOP);

//每个分类实例中放置的Input实例
    private Input[] values;

//多个参数来初始化分类实例
    Category(Input... types) { values = types; }

//分类eumMap, key表示一个Input, value表示它所属的分类实例
    private static EnumMap<Input, Category> categories = 
        new EnumMap<Input, Category>(Input.class);
    static {

//每个分类实例下的Input实例数组, 作为key, 分类实例作为value, 构建map
        for(Category c : Category.class.getEnumConstants()) 
            for(Input type : c.values)
                categories.put(type,c);
    }

//根据Input实例, 返回所属的分类
    public static Category categorize(Input input) {
        return categories.get(input);
    }
}

//上面这个分类就是得到一个根据输入的实例, 得到输入类型分类的功能

//下面这个就是自动售货机的状态机
public class VendingMachine {

//State enum, 表示当前售货机的状态, RESTING为原始状态
    private static State state = State.RESTING;

//表示售货机中收到的钱数
    private static int amount = 0;

//表示选择的商品
    private static Input selection = null;
    enum StateDuration { TRANSIENT; }

//State状态enum, 为每一状态定义next()方法, 确定下一个状态, 以及售贩等操作
    enum State {

//原始状态
        RESTING {
            void next(Input input) {

//根据输入所属类型来进行不同操作
                switch(Category.categorize(input)) {

//钱, 客人给的钱, 把数额加到售货机中收到的钱中, 转为继续收钱状态
                    case MONEY: 
                         amount += input.amount();
                         state = ADDING_MONEY;
                         break;

//退出售货机, 转为结束状态
                    case SHUT_DOWN: 
                         state = TERMINAL;
                    default: 
                }
            }
        },

//继续收钱状态
        ADDING_MONEY {
            void next(Input input) {
                switch(Category.categorize(input)) {

//继续收钱
                    case MONEY: 
                        amount += input.amount();
                        break;

//选择商品, 如果收的钱不够商品价格, 输出钱不够, 否则转换为商品结算状态
                    case ITEM_SELECTION:
                        selection = input;
                        if(amount < selection.amount())
                            print("Insufficient money for " + selection);
                        else state = DISPENSING;
                        break;

//放弃交易, 进入找钱状态
                    case QUIT_TRANSACTION:
                        state = GIVING_CHANGE;
                        break;

//退出售货机, 转为结束状态
                    case SHUT_DOWN: 
                        state = TERMINAL;
                    default:
                }
            }
        },

//结算商品状态
        DISPENSING(StateDuration.TRANSIENT) {

//从收到的钱中扣除商品价格, 进入找钱状态
            void next() {
                print("here is your " + selection);
                amount -= selection.amount();
                state = GIVING_CHANGE;
            }
        },

//找钱状态
        GIVING_CHANGE(StateDuration.TRANSIENT) {
            void next() {

//收到的钱还有剩, 找钱, 并清空收到的钱, 转换为初始状态
                if(amount > 0) {
                    print("Your change: " + amount);
                    amount = 0;
                }
                state = RESTING;
            }
        },

//结束状态
        TERMINAL {
            void output() { print("Halted"); };
        };

//每个状态实例是否是一个暂时性状态, 如果是暂时性状态, 处理完状态后, 不需要输入, 直接跳转到下一个状态
        private boolean isTransient = false;
        State() {}

//暂时性状态初始化
        State(StateDuration trans) {
            isTransient = true;
        }

//非暂时性状态, 状态改变需要输入
        void next(Input input) {
            throw new RuntimeException();
        }

//暂时性状态, 状态改变不需要输入
        void next() {
            throw new RuntimeException();
        }

//输出售货机中收到的钱
        void output() { print("amount: "+amount); }
    }

//根据输入自动运行售货机
    static void run(Generator<Input> gen) {

//遇到结束状态, 推出
        while(state != State.TERMINAL) {
            Input in = gen.next();
            System.out.println("Input: " + in);

//获取输入并根据输入执行当前状态的方法, 调转至下一状态
            state.next(in);

//从下一状态开始连续的暂时性状态, 直接执行转换下去, 直到遇到非暂时性状态
            while(state.isTransient)
                state.next();

//输出钱数
            state.output();
        }
    }
    public static void main(String[] args) throws Exception {

//从文件中按";"分隔, 读取一组Input实例, 然后运行这些实例, 查看售货机的运行状态
        Generator<Input> gen = new RandomInputGenerator();
        gen = new FileInputGenerator("VendingMachingInput.txt");
        run(gen);
    }
}
class RandomInputGenerator implements Generator<Input> {
    public Input next() { return Input.randomSelection(); }
}

class FileInputGenerator implements Generator<Input> {
    private Iterator<String> input;
    public FileInputGenerator(String fileName) {
        input = new TextFile(fileName,";").iterator();
    }
    public Input next() {
        if(!input.hasNext())
            return null;
        return Enum.valueOf(Input.class, input.next().trim());
    }
}
/*
VendingMachingInput.txt
QUARTER; QUARTER; QUARTER; CHIPS;
DOLLAR; DOLLAR; TOOTHPASTE;
QUARTER; DIME; ABORT_TRANSACTION;
QUARTER; DIME; SODA;
QUARTER; DIME; NICKEL; SODA;
ABORT_TRANSACTION;
STOP;
 */

  • 多路分发

执行的操作包含了不止一个类型未知对象的操作, 要使用多路分发

两路分发, 必须要有两个方法调用, 第一个方法调用决定第一个未知类型,  第二个调用决定第二个未知类型

下面是一个石头剪刀布的两路分发

public enum Outcome {
    WIN, LOSE, DRAW
}

//Item是这几种类型的接口, 被用作多路分发

interface Item {
    Outcome compete(Item it);
    Outcome eval(Paper p);
    Outcome eval(Scissors s);
    Outcome eval(Rock r);
}
class Paper implements Item {

//第一个方法compete()决定第一个类型, 完成第一次分发, 即发起比较的类型, 其中的参数Item是第二个类型,

//把发起比较的类型当作第二个类型的参数this, 放在第二个方法中
    public Outcome compete(Item it) { return it.eval(this); }

//第二个方法eval()决定第二个类型, 完成第二次分发, 表示被比较的类型, 它的参数是在第一次分发中确定的

//发起比较的类型, 那么可以根据具体的参数类型重载这个方法返回比较结果
    public Outcome eval(Paper p) { return DRAW; }
    public Outcome eval(Scissors s) { return WIN; }
    public Outcome eval(Rock r) { return LOSE; }
    public String toString() { return "Paper"; }
}
class Scissors implements Item {
    public Outcome compete(Item it) { return it.eval(this); }
    public Outcome eval(Paper p) { return LOSE; }
    public Outcome eval(Scissors s) { return DRAW; }
    public Outcome eval(Rock r) { return WIN; }
    public String toString() { return "Scissors"; }
}
class Rock implements Item {
    public Outcome compete(Item it) { return it.eval(this); }
    public Outcome eval(Paper p) { return WIN; }
    public Outcome eval(Scissors s) { return LOSE; }
    public Outcome eval(Rock r) { return DRAW; }
    public String toString() { return "Rock"; }
}
public class RoShambo1 {
    static final int SIZE = 20;
    private static Random rand = new Random(47);
    public static Item newItem() {
        switch(rand.nextInt(3)) {
            default: 
            case 0: return new Scissors();
            case 1: return new Paper();
            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) throws Exception {
        for(int i = 0;i < SIZE;i++)
            match(newItem(), newItem());
    }
}

这个例子没有用到enum, 而且enum是不能作为真正的类型的

下面是使用enum进行多路分发的方法

RoShamBo2.java

//这个enum的每个实例代表一种类型, 石头, 剪刀, 或布, 它们每个都存储了, 对石头, 对剪刀, 对布的胜负结果

public enum RoShamBo2 implements Competitor<RoShamBo2>{
    PAPER(DRAW, LOSE, WIN),
    SCISSORS(WIN, DRAW, LOSE),
    ROCK(LOSE, WIN, DRAW);

//对剪刀, 对石头, 对布的结果
    private Outcome vPaper, vScissors, vRock;
    private RoShamBo2(Outcome paper, Outcome scissors, Outcome rock)  {
        this.vPaper = paper;
        this.vScissors = scissors;
        this.vRock = rock;
    }

//去和另一个RoShamBo2实例比较, 根据参数是哪个实例, 返回this对这个实例类型的结果
    public Outcome compete(RoShamBo2 it) {
        switch(it) {
            default: 
            case PAPER: return vPaper;
            case SCISSORS: return vScissors;
            case ROCK: return vRock;
        }
    }
    public static void main(String[] args) {
        RoShamBo.play(RoShamBo2.class, 20);
    }
}

RoShamBo.java

public class RoShamBo {
    public static <T extends Competitor<T>>
    void match(T a, T b) {
        System.out.println(a + " vs. " + b + ": " + a.compete(b));
    }
    public static <T extends Enum<T> & Competitor<T>>
    void play(Class<T> rsbClass, int size) {
        for(int i = 0;i < size;i++)
            match(Enums.random(rsbClass),Enums.random(rsbClass));
    }
}

Competitor.java

//这个泛型只能存那个类本身

public interface Competitor<T extends Competitor<T>> {
    Outcome compete(T competitor);
}

下面是一个使用EnumMap实现多路分发的例子

public enum RoShamBo5 implements Competitor<RoShamBo5> {
    PAPER, SCISSORS, ROCK;

//这里一个EnumMap, key存发起比较的实例, value是一个EnumMap, 它的key是被比较的实例, value是比较结果

//它是一个static成员, 已经预先存储好所有类型的所有行为以及产生的所有结果
    static EnumMap<RoShamBo5,EnumMap<RoShamBo5,Outcome>> table = 
    new EnumMap<RoShamBo5,EnumMap<RoShamBo5,Outcome>>(RoShamBo5.class);
    static {
        for(RoShamBo5 it : RoShamBo5.values())
            table.put(it, new EnumMap<RoShamBo5,Outcome>(RoShamBo5.class));
        initRow(PAPER,DRAW,LOSE,WIN);
        initRow(SCISSORS,WIN,DRAW,LOSE);
        initRow(ROCK,LOSE,WIN,DRAW);
    }
    static void initRow(RoShamBo5 it, Outcome vPaper, Outcome vScissors, Outcome vRock) {
        EnumMap<RoShamBo5, Outcome> row = 
            table.get(it);
        row.put(RoShamBo5.PAPER,vPaper);
        row.put(RoShamBo5.SCISSORS,vScissors);
        row.put(RoShamBo5.ROCK,vRock);
    }

//根据EnumMap的结果, 当前实例this作为EnumMap的第一维key被get后, 得到该类型所对应的行为信息, 完成第一次分发

//第二次get被比较的实例it, 得到第二次分发后的信息
    public Outcome compete(RoShamBo5 it) {
        return table.get(this).get(it);
    }
    public static void main(String[] args) {
        RoShamBo.play(RoShamBo5.class, 20);
    }
}

19 枚举类型 Enumerated相关推荐

  1. thinking-in-java(19)枚举类型

    [0]开场白 1)关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用: 2)所有的枚举类都继承自 Enum,通过 enumClass.getSu ...

  2. enum枚举类型用法

    文章目录 1. 枚举类型和枚举变量 1.1 枚举类型的定义和声明 1.2 枚举变量的定义和声明 2. 枚举变量和枚举常量的关联对应 3. 枚举类型和变量的应用 3.1 作为判断语句中的逻辑 3.2 一 ...

  3. 浅析枚举类型(Enumerated types)

    枚举类型定义了一系列有序值的集合.枚举变量就是从这个既定的集合中取某个值.集合中的有序值可以称为元素,元素一般从0开始索引(也就是元素的顺序号). 定义一个枚举类型,采用以下的格式: type typ ...

  4. C++ 学习笔记(19)new/delete表达式、定位new、typeid、dynamic_cast、type_info、枚举类型、成员函数指针、union、位域、volatile限定符、链接指示

    C++ 学习笔记(19)new/delete表达式.定位new.typeid.dynamic_cast.type_info.枚举类型.成员函数指针.union.位域.volatile限定符.链接指示 ...

  5. C++ Primer 5th笔记(chap 19 特殊工具与技术)枚举类型

    1. 枚举类型(enumeration) 将一组整型常量组织在一起. 1.1 限定作用域 的 枚 举 类 型( scoped enumeration) 关 键 字 enum class ( enum ...

  6. 《Java SE实战指南》06-08:枚举类型(Enumerated types)

    内容导航: 前言 1.定义 2.使用场景 3.高阶应用 前言 在现实场景中,我们发现某类事物包含的名称.范围和含义是有限的,都可以列举出来. 方向:北.南.东.西: 季节:春季.夏季.秋季.冬季: 月 ...

  7. 理解Java枚举类型

    (参考资料:深入理解java enum) 1.原理:对编译后的class文件javap反编译可以看出,定义的枚举类继承自java.lang.Enum抽象类且通过public static final定 ...

  8. 将不确定变为确定~整形变量是否可以进行位运算(像枚举类型一样)

    回到目录 如果您看到这个题目,觉得有点怪,那说明你是一个高人,最起码比我高的多,呵呵. 前几天做了一个公用后台管理系统的项目,其中有一个地方涉及到权限管理的,即为每一个按钮赋一个权限,然后它权限汇总到 ...

  9. 在java中关于枚举类型的特性_java枚举类型小结

    JDK5.0之前,我们一般选择使用 interface 来保存常量组,以此来弥补 JDK 中没有枚举类型的缺陷,从JDK5.0开始,Sun引进了一个全新的关键字 enum 来定义一个枚举类.同inte ...

  10. DELPHI设置枚举类型size

    delphi枚举类型长度默认为2个字节(单字),而在C中枚举为4个字节(双字),如果需要跨这两个平台编程,传输结构时会由于数据长度不一造成灾难. 经过查找资料,原来delphi可以通过{$Z+} {$ ...

最新文章

  1. 关于Qt Designer程序/UI文件打开未响应的解决方法
  2. malware分析视频
  3. mysql组件化_组件化开发和模块化开发概念辨析
  4. 将项目依赖也打到jar包中
  5. 计算机专业伦理总结,《计算机伦理学》节译实践报告
  6. 深入理解Redis系列之SpringBoot集成Redis
  7. 百度网盘svip下载时显示下载请求中无下载速度
  8. 适合练手的10个前端实战项目(附视频+源码)
  9. 蓝桥杯官网试题 欧拉的鸡蛋
  10. Red5流媒体服务器搭建
  11. 基于python的垃圾分类程序,提供数据集(pytorch开发)
  12. 难倒高手了,c语言枚举end的作用是什么?
  13. EChart自定义饼图颜色
  14. 近期工作心得(总结篇)
  15. 《程序员》12月精彩内容:双11技术决战
  16. 小学生心算CAI系统
  17. Oracle 使用xtts升级11g-to-19c
  18. 外贸:圣诞新年祝福语语
  19. 液晶屏循环显示单色 液晶屏检测程序
  20. Node.js(六)express 框架 使用

热门文章

  1. html如何发送语音,浏览器实现HTML5发送语音功能
  2. 微信平台商户开通证书相关问题盘点
  3. Android设备上px(像素)、dpi(像素密度)、dip(密度无关像素)之间的关系
  4. 感冒为什么会流鼻涕?
  5. js表单提交的三种方式
  6. win10调整鼠标滚轮方向
  7. 大数据私房菜--Hadoop完全分布式安装
  8. java int64 类型_详解 Java 的八大基本类型,写得非常好!
  9. mac下Cornerstone显示日志问题 Cound not contact repository to read the latest log entries
  10. 牛客网刷题记录(3)组合逻辑