2017-02-01 3 views
0

나는이 질문이 여기에 무수히 많은 시간을 물었습니다. 그리고 나는 해결책을 찾기 위해 그와 다른 정보원을 수색했으나 나는 그 오류를 해결할 수 없습니다. 내 ClientPlayer 클래스 특성에 대한 getter 및 setter가 있고, 특정 단추가 호출 될 때 setter가 GUI에서 호출되며 클라이언트가 연결하여 서버에 개체를 보낸 후에 getter를 사용하려고합니다. 메소드 호출 "this.client.sendTCP (clientPlayer.getPlayerName());" ClientController에서 nullPointerException을 반환합니다.서버에 보낼 때 getter가 null을 반환하는 이유는 무엇입니까?

오류 : "JavaFX Application Thread"java.lang.IllegalArgumentException : object가 null 일 수 없습니다.

내 생각에 ClientPlayer의 새 인스턴스를 한 번 만들어서 너무 많은 문자열을 반환하므로 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 클래스에서 텍스트 필드 이름을 얻는다. –

답변

2

, 당신은 ClientPlayer 인스턴스를 생성하고에 setPlayerName() 전화 :

당신은

ClientPlayer clientPlayer = new ClientPlayer(); 

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

당신의 ClientController에서 수행해야하는 방법. 그런 다음 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

미운하지만 작동합니다 :

가확인정적 액세스. 당신의 GUI 클래스에서 : clientPlayer를 통해 것은이 , 당신은 참조하지 않는 "같은"개체 :

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

편집 :

public static ClientPlayer clientPlayer = new ClientPlayer(); 

는 당신은 당신 ClientController를 통해에서 바로 그 동일한 개체에 액세스 할 수 있습니다 ClientController에서 GUI 클래스에서와 같이. 그 객체를 어떻게 든 넘겨 주거나 정적 참조를 사용해야합니다. ClientController의 생성자에서 넘길 수도 있습니다.

Edit2가이 :

당신의 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-class를 언급하고 있습니까? GUI에서 ClientPlayer에 이름을 전달하고 설정 한 다음 GUI에서 가져 오십시오. 동일한 객체를 참조하지 않고 있지만 클래스를 인스턴스화하지 않고 클래스 메서드를 호출하는 방법을 알지 못합니다. –

+0

이것은 끔찍한 일입니다. OO 설계가 옳지 않기 때문에 해킹으로 필드를 공개하거나 정적으로 설정하지 마십시오. –

+0

@James_D'clientPlayer'가 로컬 플레이어의 이름 만 보유하고 있다면 정적으로 만드는 이유가 될 것입니다. 로컬 플레이어는 한 번만 존재하며 어디서나 이름에 액세스 할 수 있습니다. 아니면 내가 틀렸어? –