【问题标题】:Why is a static object null when passed as an argument to another class' constructor为什么将静态对象作为参数传递给另一个类的构造函数时为空
【发布时间】:2017-05-20 11:14:07
【问题描述】:

我正在用 Java 制作 2D 游戏。我有一个 Sprite 类和一个 Tile 类。首先,我在 Sprite 类中声明了一些静态 Sprite 对象

public class Sprite {   
public static Sprite grass = new Sprite(0, 0, Spritesheet.testTiles);
...

然后我在 Tile 类中声明了静态 Tile 对象,并将静态 Sprite 对象作为参数传递,如下所示:

public class Tile {
public static Tile grass = new Tile("grass", Sprite.grass);
...

但是由于某种原因,我传递的 Sprite 为空。任何想法为什么?

每当我在其他任何地方使用草对象时,我都没有问题。

【问题讨论】:

  • 可能是因为您在静态 Sprite 之前创建了静态 Tile。您的静态实例之间可能存在循环“依赖关系”。
  • 好的,问题出在循环依赖上。谢谢!
  • 当您在撰写答案帖子且不编辑问题时找到了问题的解决方案。没有“这是一个循环依赖问题”不是一个好的答案。显示具有该依赖关系的代码以及您如何修复它。

标签: java object static null


【解决方案1】:

这是完全可以预料的,静态初始化发生在不同的事件上,而这些事件在您分配之前都不会发生,所以静态属性无论如何都会为空。

有关活动的更多详细信息,请参阅此帖子

Explanation of how classloader loads static variables

【讨论】:

    【解决方案2】:

    原来是循环依赖的问题。我在 Tile 类中有一个静态变量 (TILE_SIZE),我在代码的其他地方使用了它,包括 Sprite 类。我移动了 Sprite-class 中的变量并删除了对 Tile-class 的依赖。

    原文:

    import ge.game.Tile;
    
    public class Sprite {   
    public static Sprite grass = new Sprite(0, 0, Spritesheet.testTiles);
    ...
    
    import ge.graphics.Sprite;
    
    public class Tile {
    public static Tile grass = new Tile("grass", Sprite.grass);
    public static int TILE_SIZE = 16;
    ...
    

    新:

    public class Sprite {   
    public static Sprite grass = new Sprite(0, 0, Spritesheet.testTiles);
    public static int SPRITE_SIZE = 16;
    ...
    
    import ge.graphics.Sprite;
    
    public class Tile {
    public static Tile grass = new Tile("grass", Sprite.grass);
    ...
    

    谢谢!

    【讨论】:

      【解决方案3】:

      Tile.grass 字段的初始化时间早于Sprite.grass。下面的问题提供了一些关于它的见解。

      Java : in what order are static final fields initialized?

      对此的解决方案可能是将Sprite.grassTile.grass 转换为单例,并通过一种方法访问它们:

      class Sprite {   
          private static Sprite grass;
      
          public static Sprite getGrassInstance(){
             if(grass == null){
                 grass = new Sprite(0, 0, Spritesheet.testTiles);
             }
      
             return grass;
          }
      
      }
      

      但要注意它们之间的循环依赖关系,以避免无限循环。

      【讨论】:

      • 唯一缺少的是创建一个私有/受保护的构造函数以避免创建其他实例。
      • 实现单例的正确方法几乎总是使用枚举。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      • 2017-12-20
      • 1970-01-01
      • 2012-11-14
      相关资源
      最近更新 更多