逻辑上等效的代码产生不同的结果

时间:2012-08-03 03:40:19

标签: java

我以前从未在Java中遇到过这种问题。所有这些代码和完整项目都可以在my GitHub找到。我有一个带有类层次结构的Snowflake类:

Snowflake extends SolidRectangle extends Movable extends Drawable extends Object

我的Snowflake课程中的以下两个代码部分在我的游戏中产生了不同的图形结果:

//In Snowflake class
public void decay()
{
    age++;
    color = randomSnowflakeColor();
    if(age == 5)
    {
        super.remove();
        Snowflake.Mempool.returnSnowflake(this);
    }
}

//In Snowflake class
public void decay()
{
    age++;
    color = randomSnowflakeColor();
    if(age == 5)
    {
        this.remove();
    }

public void remove()
{
    super.remove();
    Snowflake.Mempool.returnSnowflake(this);
}

SolidRectangleMovable都不会覆盖remove方法,但Drawable会覆盖以下实现:

//In Drawable class
public void remove()
{
    game.remove(this);
}

GameContent game具有以下实现:

//In GameContent class
public synchronized void remove(Drawable drawable)
{
    removeQueue.add(drawable);
}

我将免除removeQueue的详细信息,只需说明它正是您所期望的。

对于Snowflake.Mempool,我知道手动内存管理通常不是Java程序员当天的一部分,但我发现在创建和垃圾收集这些雪花时有太多的开销,所以我想我会重用旧雪花避免这种开销。请不要分心。我的问题是关于两个第一个代码块在功能上是否相同时可能会有什么不同。

那么,两个第一个代码块怎么能产生不同的结果呢?

3 个答案:

答案 0 :(得分:1)

虽然在调用decay()时会出现相同的结果,但在代码中从其他地方调用remove()时,可能会导致类的不同行为。

使用您的IDE,搜索remove()方法的用法,并且可以显示所有用法。

答案 1 :(得分:1)

在评论中你说过:

  

remove由CollisionHandler调用,它将其识别为SolidRectangle并将其称为((SolidRectangle)雪花).remove(),因此它调用了Drawable版本而不是Snowflake版本的代码。

我认为这不是一个正确的解释。

你似乎在说这个:

Snowflake snowflake = ...
((SolidRectangle) snowflake).remove();

会导致在雪花上调用重写的SolidRectangle.remove()方法。那是不对的。覆盖该方法后,除Snowflake方法(或Snowflake超类型方法)调用Snowflake外,无法在super.remove()上调用该方法。

答案 2 :(得分:0)

我明白了。问题是,由于Snowflake.Mempool充当堆栈,最近被破坏的雪花被用来制造新的雪花。我将所有Drawable元素保存在ArrayList<Drawable>中。这种组合导致某些雪花在ArrayList<Drawable>中出现两次,从而破坏了我的帧调整算法。切换到HashSet<Drawable>解决了问题。