2017-02-01 41 views
0

我知道这个问题已经在这里被问过无数次了,我已经搜索过SO和其他来源的解决方案,但我无法解决这个错误。我为我的ClientPlayer类属性设置了一个getter和setter,当调用某个按钮时,setter在GUI中调用,并且在客户端连接并将对象发送到服务器后,我想使用getter。调用方法“this.client.sendTCP(clientPlayer.getPlayerName());”在ClientController中返回一个nullPointerException。当我尝试发送到服务器时,为什么我的获得者返回null?

错误:“JavaFX Application Thread”java.lang.IllegalArgumentException:object不能为null。

我的猜测是我创建一个新的ClientPlayer实例太多,因此返回null,因为我的字符串playerName最初设置为none。但是,我不确定如何解决问题。我真的很感谢任何帮助。

public class ClientPlayer implements Serializable { 

public ClientPlayer() { 

} 

private String playerName; 

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

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

低于我的GUI代码,我设置一个按钮连接到服务器的相关部分:

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

是'ClientController'类内的'clientToGame.setOnAction ...'? –

+0

只有setter初始化你的'String playerName'并且你的变量'playerName'没有被初始化,所以它返回一个null! –

+0

不,它不是 - 它是GUI类,我从textField获取名称。 –

回答

2

在你的GUI,您可以创建一个ClientPlayer实例,并调用它setPlayerName()。然后在ClientController中,创建一个新的ClientPlayer实例(您永远不会呼叫setPlayerName()),并调用getPlayerName()。由于您从未为该实例设置了玩家名称,因此getPlayerName()当然会返回null。

您需要决定自己的责任是“拥有”ClientPlayer实例。如果是ClientController的责任,那么无论是getClientPlayer()方法添加到ClientController,并做

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

丑,但应该工作:

充分利用ClientPlayer访问静态。在您的GUI类:通过clientPlayer 的事情是,你不引用“相同”的对象:

public static ClientPlayer clientPlayer = new ClientPlayer(); 

,那么你可以访问相同的对象在ClientController通过:

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

编辑在你的ClientController中,就像在GUI-Class中一样。您应该以某种方式将该对象移交或使用静态引用。你也可以在ClientController的构造函数中交给它。

EDIT2:

如何你应该这样做

ClientPlayer clientPlayer = new ClientPlayer(); 

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

在你ClientController:

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将名称传递给ClientPlayer并设置它,然后从那里获取它。 我知道我没有引用相同的对象,但我不知道如何在不实例化类的情况下调用类方法。 –

+0

这太可怕了。不要将字段设置为公开的或静态的,当然不是两种,因为你的面向对象设计是不正确的。 –

+0

@James_D如果'clientPlayer'只保存本地播放器的名字,这将是一个静态的原因。本地玩家只存在一次,并且不会从任何地方访问该名称。或者我错了? –

相关问题