2017-02-01 6 views
0

Я знаю, что этот вопрос задавался здесь бесчисленным количеством раз, и я искал SO и другие источники для решения, но я просто не могу разрешить ошибку. У меня есть getter и setter для моего атрибута класса ClientPlayer, setter вызывается в графическом интерфейсе, когда вызывается определенная кнопка, и я хотел бы использовать getter после того, как клиент подключится и отправит объект на сервер. Вызов метода «this.client.sendTCP (clientPlayer.getPlayerName()); в ClientController возвращает исключение nullPointerException.Почему мои получатели возвращают null, когда я пытаюсь отправить сервер?

Ошибка: «Тема приложения JavaFX» java.lang.IllegalArgumentException: объект не может быть пустым.

Я предполагаю, что я создаю новый экземпляр 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

Is 'clientToGame.setOnAction ...' внутри класса 'ClientController'? –

+0

Получатель возвращает значение только в том случае, если сеттер инициализирует ваше '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); 
}); 

и удалить ClientPlayer полностью из вашего класса GUI.Если это ответственность класса 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 доступ статический. В вашем графического интерфейса класса:

public static ClientPlayer clientPlayer = new ClientPlayer(); 

, то вы можете получить доступ к этому тот же объект в вашем ClientController через:

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

Edit: Дело в том, что вы не ссылаться на «тот же» объект через clientPlayer в вашем ClientController, как и в GUI-классе. Вы должны каким-то образом передать этот объект или использовать статическую ссылку. Вы также можете передать его в конструкторе 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-class? Я хочу, чтобы GUI передал имя клиенту и установил его, а затем получил его оттуда. Я знаю, что я не ссылаюсь на один и тот же объект, но я не знаю, как еще вызвать методы класса без создания экземпляров классов. –

+0

Это ужасно. Не делайте поля общедоступными или статичными, и, конечно же, не обоими, как взломать, потому что ваш дизайн OO неправильный. –

+0

@James_D, если 'clientPlayer' содержит только имя локального игрока, это было бы причиной для его статичности. Локальный игрок существует только один раз, и ему не повредит доступ к названию из любого места. Или я ошибаюсь? –

 Смежные вопросы

  • Нет связанных вопросов^_^