Java 引用传递不起作用?

Java Pass-by-reference not working?

我正试图在 Java 中制作这个小游戏,但我似乎偶然发现了一个变量引用问题。 我的实体 class 是 Player 的扩展,它保留了一个 Dimension 类型的变量。 这个维度通过实体的构造函数设置 class 像这样:

protected Dimension dimension;

public Entity(Dimension dimension) {
    this.dimension = dimension;
}

在我的播放器 class 中,这是我通过他的构造函数传递维度对象的方式:

public Player(Dimension dimension) {
    super(dimension);
}

我还有一个游戏 class,它保留所有可能的维度,以及一个名为 activedimension 的额外变量,它保留对活动游戏维度的引用。

private Dimension activedimension;
private Dimension overworld;
private Dimension otherdimension;

public Game() {
    overworld = new OverWorldDimension();
    otherdimension = new OtherDimension();
    activedimension = overworld;
}

当我想要重置主世界维度时,我使用这个方法:

public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension = overworld;
}

现在,每当我从任何地方调用此 resetOverWorld 方法时,似乎我的 activedimension 确实刷新了,但存储在 Player/Enitity class 中的维度却没有。 我是 Java 的新手,所以我不知道通过构造函数和方法传递的变量引用是否有问题。 我的应用程序似乎在某处复制了一个维度对象而不是传递引用,但我不知道在哪里。

欢迎任何帮助或想法。 提前致谢 ~克里克

您不保存对变量 overworld 的引用,而是保存对 overworld 值的引用:

this.dimension = dimension;

因此当游戏中的引用发生变化时,您必须手动更新实体的引用,否则它将指向旧值,因为它独立于变量 overworld。

您将一个维度对象传递给您的 Player 对象,它在其字段之一中存储对该对象的引用。

在您的 Game 对象中,您将 activedimension 设置为引用 Dimension 对象。通过更改其值,您可以将其更改为引用不同的 Dimension 对象。

即使 activedimension 用于引用您传递给 Player 的同一个 Dimension 对象,将其更改为不同的 Dimension 对象也不会改变哪个对象是在 Player.

中引用

考虑一下,如果系统启动是这样的:

Game
-  activedimension --> Dimension object A

Player
- dimension --> Dimension object A

Dimension object A 的更改将被 PlayerGame 对象看到。

但是,将 activedimension 更改为指向 Dimension object B,一个完全不同的对象不会使 dimension 更改为指向它。

Game
-  activedimension --> Dimension object A

Player
- dimension --> Dimension object B

问题是您没有更新 Player class 中的引用。当您将 Dimension 存储在 Entity 构造函数中时,您是在内存中存储对该 Dimension 的引用。在您的 resetOverWorld() 方法中,您将 overworldactivedimension 变量更改为指向新的 OverWorldDimension 但其他地方的所有引用(例如您的 Entity 对象)都没有改变了。他们仍然参考最初的Dimension他们被构造。

您可能需要考虑使用 DimensionTracker class 代替您的 Entity,这样您就可以从一个位置更改它的内部 Dimension。否则你需要更新每个 Entity 以引用新的 Dimension.

public class DimensionTracker {
    public Dimension dimension;
    public DimensionTracker(Dimension d) {
        dimension = d;
    }
}

...

protected DimensionTracker dimensionTracker;

public Entity(DimensionTracker dt) {

    dimensionTracker = dt;
}

...

public Player(DimensionTracker dt){
    super(dt);
}

...

private DimensionTracker activedimension;
private Dimension overworld;
private Dimension otherdimension;

public Game() {
    overworld = new OverWorldDimension();
    otherdimension = new OtherDimension();
    activedimension.dimension = overworld;
}

...

public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension.dimension = overworld;
}
public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension = overworld;
}

这只会更新游戏 class 变量 private Dimension activedimension ;

调用 resetOverWorld() 后,您必须通过执行

之类的操作来设置对实体 class 的新引用
entity.setDimension(activedimension)