【问题标题】:Java Pass-by-reference not working?Java 引用传递不起作用?
【发布时间】:2015-08-26 09:21:01
【问题描述】:

我正在尝试用 Java 制作这个小游戏,但我似乎偶然发现了一个变量引用问题。 Player 扩展自我的 Entity 类,它保留一个 Dimension 类型的变量。 此 Dimension 通过 Entity 类的构造函数设置,如下所示:

protected Dimension dimension;

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

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

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

我还有一个 Game 类,它保留所有可能的维度,以及一个名为 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 类中的维度却没有。 我对 Java 还很陌生,所以我不知道我是否对通过构造函数和方法传递的变量引用做错了。 我的应用程序似乎在某处复制维度对象而不是传递引用,但我不知道在哪里。

欢迎任何帮助或想法。 提前致谢 〜Krikke

【问题讨论】:

  • Java 是按值传递的。编辑:而且我看不到您在 Entity/Player 类中更新副本的位置。可以出示一下代码吗?
  • 您正在重新分配您传递的引用。想象一下你住在#5,你给每个人你的地址(传递参考),当他们写信给你的地址时,你会得到帖子(调用方法)。然后你偷偷搬家,不告诉任何人。你的帖子去哪儿了?
  • @Mike Java 永远不会通过引用传递。它通过对象的值传递引用。
  • @Kyle 你说的很对,我的语义错了!

标签: java variables reference pass-by-reference


【解决方案1】:

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

this.dimension = dimension;

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

【讨论】:

    【解决方案2】:

    您将维度对象传递给您的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
    

    【讨论】:

      【解决方案3】:

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

      您可能需要考虑使用您的Entity 可以容纳的DimensionTracker 类,从而允许您从一个位置更改其内部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;
      }
      

      【讨论】:

      • 非常感谢!一段时间以来,我试图弄清楚出了什么问题。这个答案回答了一切!标记为正确:)
      【解决方案4】:
      public void resetOverWorld() {
          overworld = new OverWorldDimension();
          activedimension = overworld;
      }
      

      这只会更新 Game 类变量 private Dimension activedimension ;

      在调用resetOverWorld() 之后,您必须通过执行类似的操作来设置这个对实体类的新引用

      entity.setDimension(activedimension)
      

      【讨论】:

        猜你喜欢
        • 2011-02-19
        • 2017-12-20
        • 2012-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多