2011-09-14 122 views
1

我從頭開始用Java構建我的第一款遊戲。我已經決定將遊戲的主要操作(處理輸入等)集中在一起的GameWorld類最好作爲一個單例實現(使用枚舉)。下面是枚舉的相關代碼。Java Singleton空指針異常

public enum GameWorld { 
    INSTANCE; 
    private static InputController input = InputController.getInput(); 
    public EntityPlayer player = new EntityPlayer(10, 10, 5, 5); 

    public static GameWorld getWorld() { 
     return INSTANCE; 
    } 

    public InputController getInputController() { 
     return input; 
    } 
} 

唯一的例外發生在EntityPlayer的構造。代碼和堆棧跟蹤如下。

public class EntityPlayer implements Entity, InputListener { 
    private int xPos; 
    private int yPos; 
    private int width; 
    private int height; 

    // Velocity of object 
    // Determines where it sets itself on update 
    private int xVel; 
    private int yVel; 
    private GameWorld world; 

    private InputController input; 

    private boolean solid; 

    public EntityPlayer(int x, int y, int width, int height) { 
     xPos = x; 
     yPos = y; 
     this.width = width; 
     this.height = height; 
     solid = true; 
     xVel = 0; 
     yVel = 0; 
     world = getWorld(); 
     input = world.getInputController(); 
     input.registerKeyListener(this); 
    } 

    @Override 
    public Graphics draw(Graphics g) { 
     g.setColor(Color.yellow); 
     g.fillRect(xPos, yPos - height, width, height); 
     return g; 
    } 

    @Override 
    public void update() { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public int getXPos() { 
     return xPos; 
    } 

    @Override 
    public int getYPos() { 
     return yPos; 
    } 

    @Override 
    public Rectangle getRect() { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public boolean isSolid() { 
     return solid; 
    } 

    @Override 
    public void kill() { 

    } 

    @Override 
    public GameWorld getWorld() { 
     return GameWorld.getWorld(); 
    } 

    @Override 
    public void sendKeyPress(KeyEvent ke) { 
     System.out.println(ke.getKeyChar()); 
    } 

    @Override 
    public void sendMouseMove(MouseEvent me) { 

    } 

} 

堆棧跟蹤:

Exception in thread "main" java.lang.ExceptionInInitializerError 
    at com.pvminecraft.gameworld.Main.<clinit>(Main.java:14) 
Caused by: java.lang.NullPointerException 
at com.pvminecraft.gameworld.entities.EntityPlayer.<init>(EntityPlayer.java:45) 
at com.pvminecraft.gameworld.GameWorld.<init>(GameWorld.java:15) 
at com.pvminecraft.gameworld.GameWorld.<clinit>(GameWorld.java:13) 
... 1 more 

線Main.java的14我讓遊戲世界的另一個實例進行測試。我不知道爲什麼這是拋出一個異常。如果我在EntityPlayer中刪除對GameWorld的引用,它就會消失。如果您需要Main.java的代碼,請在評論中告訴我,我會發布它。 謝謝!

編輯: EntityPlayer中的第45行是「input = world.getInputController();」我很確定這個世界是空的,儘管我不知道爲什麼。

+1

什麼是45行?哦,這個? 'input = world.getInputController();'? –

+2

這不是一個'enum'的好用法... –

+0

我從這個想法得到:http://stackoverflow.com/questions/70689/efficient-way-to-implement-singleton-pattern-in-java它的評價很高,他列舉了一本我聽說過的好書。我認爲這是正確的。我錯了嗎? –

回答

2

你正在轉圈。

您想初始化GameWorld.INSTANCE變量。在你這樣做之前,你必須初始化GameWorld類的所有字段。初始化所有字段後,將分配變量INSTANCE。在此之前,它仍然有默認值null

初始化期間,字段player被初始化。在初始化中,您已經訪問INSTANCE字段。所以你有一個循環依賴。

你真的必須解耦你的類,以便它們變得更加獨立於彼此。

+0

好吧。我會。謝謝。 –

+0

+1好的。當你發佈這個消息時,我剛剛知道'INSTANCE'是如何'空'的。 –

+0

我仍然不完全清楚最好的方式來做到這一點。我已經添加了一個現在可用的setPlayer方法。謝謝。 –

0

我沒有看到任何保證表達

InputController.getInput() 

返回非空。而且由於你的代碼非常容易調試(每行至少有一個NullPointerException),查看哪個變量爲空應該是微不足道的。如上所述,我懷疑input

+0

這是世界。我以前在那裏有printlns進行調試,這告訴了我這樣的情況。 –