1. 概述

在这个教程中,我们将学习如何从一个枚举(enum)生成随机值。

2. 使用静态方法生成随机枚举值

首先,我们将创建一个静态函数,它从特定的枚举集返回一个随机生成的值。枚举值代表一组常量,但仍然可以在枚举类体中声明静态方法。我们将利用静态方法作为辅助工具来生成随机枚举值。

在枚举类体内部声明一个静态方法,返回一个枚举值。这个方法会调用Random类的nextInt()方法,我们将其命名为randomDirection()

public enum Direction {
    EAST, WEST, SOUTH, NORTH;
    
    private static final Random PRNG = new Random();

    public static Direction randomDirection()  {
        Direction[] directions = values();
        return directions[PRNG.nextInt(directions.length)];
    }
}

randomDirection()中,我们使用一个整数参数调用nextInt()方法。nextInt()方法会返回一个随机数来访问directions数组;因此,我们需要确保传递给nextInt()的整数不会超出数组的范围,通过传入一个边界参数。边界参数是方向总数,我们知道它不会超过数组的大小。

此外,每次调用randomDirection()方法时,values()方法都会创建一个枚举值的副本。为了提高性能,我们可以在生成随机索引后访问一个final成员变量列表:

private static final Direction[] directions = values();

现在,randomDirection()方法看起来如下:

public static Direction randomDirection() { 
    return directions[PRNG.nextInt(directions.length)]; 
}

最后,我们可以通过调用该方法来生成一个随机的Direction

Direction direction = Direction.randomDirection();

3. 使用泛型生成随机枚举值

同样,我们也可以使用泛型来生成随机枚举值。通过使用泛型,我们创建一个类,接受任何类型的枚举数据来生成随机值:

public class RandomEnumGenerator<T extends Enum<T>> {
    private static final Random PRNG = new Random();
    private final T[] values;

    public RandomEnumGenerator(Class<T> e) {
        values = e.getEnumConstants();
    }

    public T randomEnum() {
        return values[PRNG.nextInt(values.length)];
    }
}

请注意,randomEnum()方法与上一示例中的randomDirection()方法类似。不同之处在于RandomEnumGenerator类有一个构造函数,它期望接收一个获取常量值的枚举类型。

我们可以使用RandomEnumGenerator类来生成随机方向,如下所示:

RandomEnumGenerator reg = new RandomEnumGenerator(Direction.class);
Direction direction = (Direction) reg.randomEnum();

这里我们使用了上一节中的Direction枚举类。RandomEnumGenerator接受这个类,而direction对象将引用Direction类中的一个常量值。

4. 总结

在这篇教程中,我们了解了如何从枚举中获取随机值。我们探讨了两种方法:首先,我们在枚举类中使用静态方法,这种方法生成的随机值严格限制在方法声明的枚举类内。此外,我们还看到了如何通过缓存常量值来提高性能。最后,我们使用泛型,通过一个接受任何枚举类型的类来获取随机值。

如往常一样,本文的完整代码示例可在GitHub上找到。