2017-02-01 3 views
0

私はこの質問がここで何度も何回も尋ねられていることを知っています。私はSOなどの情報源を検索しましたが、エラーを解決できません。 ClientPlayerクラス属性のgetterとsetterがあり、特定のボタンが呼び出されたときにsetterがGUIで呼び出され、クライアントが接続してオブジェクトをサーバーに送信した後にgetterを使用したいと考えています。メソッドを呼び出す "this.client.sendTCP(clientPlayer.getPlayerName());" ClientControllerのnullPointerExceptionを返します。サーバーに送信しようとすると、getterがnullを返すのはなぜですか?

エラー:「JavaFXアプリケーションスレッド」java.lang.IllegalArgumentException:オブジェクトをnullにすることはできません。

私の推測では、ClientPlayerの新しいインスタンスを1回作成すると、playerNameが元々noneに設定されているためnullが返されることになります。しかし、問題を解決する方法についてはわかりません。私は本当に何か助けていただければ幸いです。私は、サーバーに接続するためのボタンを設定し、私のGUIコードの関連部分の下

public class ClientPlayer implements Serializable { 

public ClientPlayer() { 

} 

private String playerName; 

public void setPlayerName(String playerName) { 
    this.playerName = playerName; 
    } 

public String getPlayerName() { 
    return this.playerName; 
    } 
} 

ClientPlayer clientPlayer = new ClientPlayer(); 

    clientToGame.setOnAction((ActionEvent w) -> { 
     clientPlayer.setPlayerName(clientNameText.getText()); 
     clientController.connect(); 
     window.setScene(lobbyScene); 
    }); 

ここで私が取得しようとする私のクライアントクラスのビットがありますサーバーに名前と送信:

public class ClientController() { 
    ClientPlayer clientPlayer = new ClientPlayer(); 

    public void connect() { 
    if (client.isConnected()) { 
     Logger.getLogger(getClass().getName()).log(Level.INFO, "You are  already connected to :{0}", config.getHost()); 
     return; 
    } 
    this.client.start(); 
    try { 
     this.client.connect(5000, config.getHost(), config.getTCPPort()); 
     System.out.println("Successfully connected to " + config.getHost()); 
     this.client.sendTCP(clientPlayer.getPlayerName()); 

    } catch (IOException ex) { 
     Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Server connection failed: {0}", ex.getMessage()); 
     throw new RuntimeException(ex); 
    } 

    MessageRegistry.registerMessages(client.getKryo()); 
    this.client.addListener(listener); 
    } 
} 
+0

です'ClientToGame.setOnAction ...'は 'ClientController'クラスの中にありますか? –

+0

getterは、setterが 'String playerName'を初期化し、変数' playerName'が初期化されていないので、nullを返した場合にのみ値を返します。 –

+0

いいえ、そうではありません。GUIクラスで、名前をtextFieldから取得します。 –

答えて

2

、あなたはClientPlayerインスタンスを作成し、その上にsetPlayerName()を呼び出します。次にClientControllerで、setPlayerName()という名前ではない新しいClientPlayerインスタンスを作成し、getPlayerName()を呼び出します。そのインスタンスのプレーヤー名は決して設定しないので、getPlayerName()はもちろんnullを返します。

ClientPlayerインスタンスを所有する責任は誰に決定する必要があります。それはClientControllerの責任である場合は、どちらかClientControllergetClientPlayer()メソッドを追加し、

clientToGame.setOnAction((ActionEvent w) -> { 
    clientController.getClientPlayer().setPlayerName(clientNameText.getText()); 
    clientController.connect(); 
    window.setScene(lobbyScene); 
}); 

を行うと、あなたのGUIクラスから完全ClientPlayerを削除します。それはそれを所有するGUIクラスの責任である場合には、connect()方法にそれへの参照を渡すと、コントローラからClientPlayerフィールドを削除:

public class ClientController() { 
    // ClientPlayer clientPlayer = new ClientPlayer(); 

    public void connect(ClientPlayer clientPlayer) { 
    if (client.isConnected()) { 
     Logger.getLogger(getClass().getName()).log(Level.INFO, "You are  already connected to :{0}", config.getHost()); 
     return; 
    } 
    this.client.start(); 
    try { 
     this.client.connect(5000, config.getHost(), config.getTCPPort()); 
     System.out.println("Successfully connected to " + config.getHost()); 
     this.client.sendTCP(clientPlayer.getPlayerName()); 

    } catch (IOException ex) { 
     Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Server connection failed: {0}", ex.getMessage()); 
     throw new RuntimeException(ex); 
    } 

    MessageRegistry.registerMessages(client.getKryo()); 
    this.client.addListener(listener); 
    } 
} 

そしてもちろん

clientToGame.setOnAction((ActionEvent w) -> { 
    clientPlayer.setPlayerName(clientNameText.getText()); 
    clientController.connect(clientPlayer); 
    window.setScene(lobbyScene); 
}); 
-1

醜いが、動作するはずです:

をを作ります静的にアクセスします。

public static ClientPlayer clientPlayer = new ClientPlayer(); 

あなたは経由でClientControllerで、非常に同じオブジェクトにアクセスすることができます:あなたのGUIクラスで

... 
this.client.sendTCP(MyGuiClass.clientPlayer.getPlayerName()); 
... 

編集: 事がある、あなたがclientPlayerを経由して「同じ」オブジェクトを参照しませんあなたのClientControllerの中でGUIクラスと同じように。あなたは何とかそのオブジェクトを手渡すか、静的な参照を使用する必要があります。 ClientControllerのコンストラクタでそれを渡すこともできます。

EDIT2:あなたはそれをあなたのClientControllerで

ClientPlayer clientPlayer = new ClientPlayer(); 

    clientToGame.setOnAction((ActionEvent w) -> { 
     clientPlayer.setPlayerName(clientNameText.getText()); 
     clientController.connect(clientPlayer); 
     window.setScene(lobbyScene); 
    }); 

を行う必要がありますどのように

:あなたのGUIで

public void connect(ClientPlayer player) { 
    this.clientPlayer = player; 
    if (client.isConnected()) { 
     Logger.getLogger(getClass().getName()).log(Level.INFO, "You are already connected to :{0}", config.getHost()); 
     return; 
    } 
    this.client.start(); 
    try { 
     this.client.connect(5000, config.getHost(), config.getTCPPort()); 
     System.out.println("Successfully connected to " + config.getHost()); 
     this.client.sendTCP(player.getPlayerName()); 

    } catch (IOException ex) { 
     Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Server connection failed: {0}", ex.getMessage()); 
     throw new RuntimeException(ex); 
    } 

    MessageRegistry.registerMessages(client.getKryo()); 
    this.client.addListener(listener); 
} 

+0

私は今guiクラスを指していますか?私は、GUIがClientPlayerに名前を渡して、そこからそれを取得するようにします。 私は同じオブジェクトを参照していないことを知っていますが、クラスをインスタンス化せずにクラスメソッドを呼び出す方法がわかりません。 –

+0

これは恐ろしいです。あなたのオブジェクト指向設計が正しくないので、フィールドをパブリックにするか、静的にするか、あるいは必ず両方をハックにしないでください。 –

+0

@James_D 'clientPlayer'がローカルプレーヤーの名前しか保持しない場合、これは静的にする理由になります。ローカルプレイヤーは一度だけ存在し、どこからでも名前にアクセスすることに傷つきません。または私は間違っていますか? –

関連する問題