【问题标题】:Changing the class of an object in an arraylist更改数组列表中对象的类
【发布时间】:2013-12-07 20:49:26
【问题描述】:

好的,所以我有一个蜂箱模型,其中包含一个称为单元格的蜜蜂数组列表。我想要发生的是当蜜蜂健康达到 0 时,它会从数组列表中删除(鸡蛋不需要吃)。蜜蜂的年龄每天增加 1,如果有足够的食物喂它,它的健康也会增加 1(最多 3)。如果没有足够的食物,那么生命值会减少 1(直到它从数组列表中删除时达到 0)。蜜蜂类是抽象的,并且有子类,如卵、幼虫、蛹等。当卵的年龄 > 3 岁时,它会变成幼虫,而幼虫会在 7 岁时变成蛹。但是,我在编码时遇到了严重的问题。如果健康达到0罚款,我已经设法获得喂养,健康增加/减少和移除,但我无法弄清楚如何将我的卵“进化”成幼虫。

我的代码:

public class Hive {

    ArrayList<Bee> cells = new ArrayList<Bee>();
    //some code omitted

    public void anotherDay(){
        for(int i = 0;i<cells.size(); i++){
            System.out.println(cells.get(i));
            Bee bee = cells.get(i);
            try{
                bee = bee.anotherDay();
            }catch(Exception e){
                cells.remove(i);
            }
        }

女王级:

public class Queen extends Bee{
//some code omitted

    public Bee anotherDay() throws Exception{
        eat();
        age++;
        if(age%3 == 2){
            hive.addBee(new Egg());
        }
        return this;
    } 

    public boolean eat() throws Exception{
        if(hive.honey >= 2){
            hive.takeHoney(2);
            if(health < 3){
                health++;
            }return true;
        }
            health -= 1;
            if(health == 0){
                throw new Exception(); 
            }
            return false;
    }

卵类(幼虫和蛹的方法类似):

public class Egg extends Bee {
//some code omitted
    public Bee anotherDay(){
    age = age++;
    if (age>3){
        return new Larvae();
    }else{
    return this;
    }

}

【问题讨论】:

    标签: java class exception arraylist


    【解决方案1】:

    由于您的策略似乎是返回一个 Bee 对象,您只需将列表元素“替换”为返回值即可。

    但我还看到了其他一些事情。首先是您使用异常来执行程序逻辑。不要这样做。特别是因为你只是抛出一个空白异常,这样做你也会吃掉所有其他异常。

    第二个是您在迭代列表时正在修改列表。这通常是个坏主意,在某些情况下甚至可以throw a ConcurrentModificationException

    当你的女王下蛋时,列表会变大 1。由于您的循环基于列表大小,因此新鸡蛋将包含在迭代中。这意味着您的卵子会在 1 天大时自动开始,而不是 0 天大。去除死蜜蜂也是如此。在迭代时删除它们可能意味着您跳过下一只蜜蜂。

    我不确定您的某些逻辑打算做什么,例如 Queen#eat 中的内容,但这里试图展示一个更稳定的版本:

    public class Hive {
    
        ArrayList<Bee> cells = new ArrayList<Bee>();
    
        public void anotherDay() {
            List<Bee> dead = new ArrayList<Bee>();
            int size = cells.size();
    
            for(int i = 0; i < size; i++) {
                Bee bee = cells.get(i);
                System.out.println(bee);
    
                // return null if the bee is dead
                if ((bee = bee.anotherDay()) == null) {
                    dead.add(cells.get(i));
                } else {
                    cells.set(i, bee);
                }
            }
    
            cells.removeAll(dead);
        }
    }
    
    public class Queen extends Bee {
    
        public Bee anotherDay() {
            eat();
            if (health == 0) {
                return null;
            }
    
            age++;
            if (age % 3 == 2) {
                hive.addBee(new Egg());
            }
    
            return this;
        } 
    
        public boolean eat() {
            if(hive.honey >= 2) {
                hive.takeHoney(2);
                if(health < 3){
                    health++;
                }
                return true;
            }
            health -= 1;
            return false;
        }
    }
    

    您不必返回 null,这只是一个显而易见的选择。你也可以有一个像isDead()这样的标志:

    class SomeBee extends Bee {
    
        boolean isDead() {
            return health <= 0;
        }
    
        Bee anotherDay() {
            eat();
            return this;
        }
    }
    
    for (/* i...size */) {
        Bee bee = cells.get(i);
        if ((bee = bee.anotherDay()).isDead()) {
            dead.add(bee);
        }
        cells.set(i, bee);
    }
    

    或类似以下内容:

    abstract class Bee {
        static final Bee DEAD_BEE = new Bee() {
            @Override
            Bee anotherDay() {
                return this;
            }
        };
    }
    
    class SomeBee extends Bee {
        @Override
        Bee anotherDay() {
            if (/* is dead */) {
                return Bee.DEAD_BEE;
            } else {
                ...
    
    class Hive {
        void anotherDay() {
            ...
    
            for (/*    */) {
    
                Bee next = bee.anotherDay();
                if (next == Bee.DEAD_BEE) {
                    /* it's dead */
                } else {
                    ...
    

    由于递增错误,您的鸡蛋不会变老:

    age = age++;
    

    后缀增量计算为增量之前的值。所以这基本上就像说age = age;。增量无处可去。在这种情况下只需删除分配,它是多余的:

    age++;
    

    还有一个前缀增量 (++age),它计算为增量后的值。有时您确实想增加/减少一个变量并立即使用它,因此这是一个需要了解的重要区别。

    例如,您可以这样遍历数组:

    int i = 0;
    while (i < array.length)
        System.out.println(array[i++]);
    

    后缀和前缀增量可以定义为如下方法:

    class Primitive_int {
        int val;
    
        // "++value"
        int prefixIncrement() {
            val = val + 1;
            return val;
        }
    
        // "value++"
        int postfixIncrement() {
            int old = val;
            val = val + 1;
            return old;
        }
    }
    

    【讨论】:

    • 非常感谢!!这是一个巨大的帮助。然而幼虫仍然没有被添加到我的蜂巢中 =/
    • 没问题。我假设您指的是if (age % 3) hive.addBee 位。我看不出它不能在您包含的代码中工作的原因,所以它可能是您省略的某个地方。确保女王正确地引用了蜂巢。
    • 不,那是为了鸡蛋——非常混乱!!在您回答的开头,您说我可以用返回值“替换”列表项,因为我在queen中的 anotherDay 方法返回一只蜜蜂,我认为 cells.set(i, bee) 会这样做,但是多少天把蛋传出去不要变成幼虫!!
    【解决方案2】:
    public class Hive {
    
        ArrayList<Bee> cells = new ArrayList<Bee>();
        //some code omitted
    
        public void anotherDay(){
            for(int i = 0;i<cells.size(); i++){
                System.out.println(cells.get(i));
                Bee bee = cells.get(i); // bee --> egg
                try{
                    bee = bee.anotherDay(); // now bee --> Larve
                    cells.set(i,bee); // don't forget to set larve where bee was!
                }catch(Exception e){
                    cells.remove(i);
                }
        }
    

    【讨论】:

    • 我刚试过这个,现在当运行 hive 中的 anotherDay() 方法时,由于某种原因,我得到了一个无限循环!
    • 是的,我就是这么做的 =/
    • 使用cells.set(i, bee),它应该可以工作。我的坏:)
    • 啊,谢谢你已经摆脱了无限循环的问题。不幸的是,似乎没有幼虫添加到蜂巢中 =(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    相关资源
    最近更新 更多