Java静态变量,我做错了什么?

时间:2014-03-28 18:13:45

标签: java

我试图确保没有两个类的实例具有相同的优先级/ id值。我目前正试图为每个优先级值保存布尔值,但在我的单元测试中从不抛出异常。为什么这段代码不起作用?

public abstract class AbstractCard implements Card {
    private int priority;
    protected Robot robot;

    private static boolean[] prioritiesUsed = new boolean[1000]; // defaults to false

    ...[omitted code]

protected AbstractCard(int lowPriority, int highPriority) {

        // TODO: this doesn't work!
        // different instances can have the same priority right now
        // that shouldn't be allowed, so something's broken somewhere here!
        // this code will still work as good as the placeholder code we had, so I'm pushing this broken code

        Random random = new Random();

        // try a few times to get a random priority that hasn't been used before
        for (int tries = 0; tries < 10; tries++) {
            // get random priority p in range low <= p <= high
            this.priority = random.nextInt((highPriority - lowPriority) + 1) + lowPriority;

            // is this priority already taken?
            if (prioritiesUsed[this.priority] == false) {
                prioritiesUsed[this.priority] = true;
                return;
            }
        }

        // screw randomizing, it didn't work. Let's just increment untill we find a free one.
        int infiniteLoopDetector = this.priority - 1;
        while (prioritiesUsed[this.priority]) {
            this.priority++;

            if (this.priority > highPriority) { // about to leave range, wrap around and try from lower bound
                this.priority = lowPriority;
            }

            if (this.priority == infiniteLoopDetector) {
                throw new DeckPriorityIntervalFilledException(
                    String.format("All priority values between %d and %d are already taken by other cards",
                            lowPriority, highPriority));
            }
        }

    }

这里是单元测试,使用intellij中的groovy

注意:class MoveCard extends AbstractCard

void testConstructor() {
        // try to create 101 cards inside a 100 card interval
        try {
            for (int i = 0; i < 100; i++) {
                new MoveCard(42, 141); // 42 <= priority <= 141
            }
        } catch (RuntimeException e) {
            fail("exception thrown: " + e.toString());
        }

        // and add the 101st one, that should throw an exception
        try {
            AbstractCard ac = new MoveCard(42, 141);
            println(ac.priority);
            ac = new MoveCard(42, 141);
            println(ac.priority);
            ac = new MoveCard(42, 141);
            println(ac.priority);
            ac = new MoveCard(42, 141);
            println(ac.priority);
            ac = new MoveCard(42, 141);
            println(ac.priority);


            fail("exception wasn't thrown!");
        } catch (RuntimeException e) {
            // all ok
        }
    }

1 个答案:

答案 0 :(得分:1)

您根本就没有设置

prioritiesUsed[this.priority] = true;

while循环后尝试优先级。

一般提示:

在调试过程中,我强烈建议使用使用特定随机种子初始化的公共Random实例。此实例将始终提供相同的随机数序列,使运行可重现。因此,用

替换您的本地Random实例
private static Random random = new Random(0);

然而,你的方法是......不是很优雅。正如其他人所指出的那样,用Set来管理优先事项会容易得多。如建议的那样,您可以使用工厂来封装优先级的管理,但代码粗略看起来像这样:

abstract class AbstractCard
{
    int priority;
    private static Set<Integer> usedPriorities = new LinkedHashSet<Integer>();
    private static Random random = new Random(0);

    protected AbstractCard(int lowPriority, int highPriority)
    {
        Set<Integer> availablePriorities = new LinkedHashSet<Integer>();
        for (int i = lowPriority; i <= highPriority; i++)
        {
            availablePriorities.add(i);
        }
        availablePriorities.removeAll(usedPriorities);
        if (availablePriorities.size() == 0)
        {
            throw new RuntimeException(String.format(
                "All priority values between %d and %d "
                    + "are already taken by other cards", lowPriority,
                highPriority));
        }
        List<Integer> priorities = new ArrayList<Integer>(availablePriorities);
        int index = random.nextInt(priorities.size());
        this.priority = priorities.get(index);
        usedPriorities.add(this.priority);
    }

}