Java 尝试向客户端套接字发送消息时出现NullPointerException
我有一个ServerHandler类,它创建一个新的PrintWriter并将其存储到PrintWriter数组中,消息通过向selectedId整数提供应该接收消息的客户端的ID号来发送。当我在ServerHandler类中调用SendMessage()方法时,它会毫无问题地发送消息,但当我尝试从包含GUI的类中调用SendMessage(“some message”)方法时,它会给我一个NullPointerException posljiSporocilo()是实际的SendMessage(),因为有些方法使用的是我的语言Java 尝试向客户端套接字发送消息时出现NullPointerException,java,multithreading,sockets,nullpointerexception,Java,Multithreading,Sockets,Nullpointerexception,我有一个ServerHandler类,它创建一个新的PrintWriter并将其存储到PrintWriter数组中,消息通过向selectedId整数提供应该接收消息的客户端的ID号来发送。当我在ServerHandler类中调用SendMessage()方法时,它会毫无问题地发送消息,但当我尝试从包含GUI的类中调用SendMessage(“some message”)方法时,它会给我一个NullPointerException posljiSporocilo()是实际的SendMessage
import java.net.*;
import java.io.*;
import java.awt.*;
public class ServerHandler implements Runnable{
Socket klientSocket;
static int userCounter = 0;
static int selectedId = 0;
BufferedReader reader;
static PrintWriter writer;
static PrintWriter[] writerHolder = new PrintWriter[10];
static outputHelper out = new outputHelper();
public ServerHandler(Socket klientSocket) throws IOException
{
userCounter++;
this.klientSocket = klientSocket;
writer = new PrintWriter(this.klientSocket.getOutputStream());
writerHolder[userCounter] = writer;
InputStreamReader inReader = new InputStreamReader(this.klientSocket.getInputStream());
reader = new BufferedReader(inReader);
out.frameOutput(this.klientSocket.getInetAddress().toString(), "Server sprejel povezavo:");
selectedId = 1;
posljiSporocilo("AutoSent");
当我在实际类中调用posljiSporocilo()方法时,它会将消息发送到客户端。}
public ServerHandler(){
// Do not launch the main Constructor
}
public void run(){
String inMessage = null;
try{
while((inMessage = reader.readLine()) != null){
System.out.println("Server Sprejel: " + inMessage);
}
}catch(IOException ex){
ex.printStackTrace();
}
}
public void selectId(int id){
selectedId = id;
out.frameOutput("ID Changed to: " + selectedId, "ID change");
}
public void posljiSporocilo(String message){
try
{
writerHolder[selectedId].println(message);
writerHolder[selectedId].flush();
}catch(Exception ex)
{
out.frameOutput("ERROR Trying to send a message", "ERR_MESSAGE:");
ex.printStackTrace();
}
}
}
包含GUI内容的类:
package homeControl;
IMPORTS
public class mainWindow extends JFrame {
private JPanel contentPane;
private JTextField messageTextField;
ServerHandler svr = new ServerHandler();
outputHelper o = new outputHelper();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
mainWindow frame = new mainWindow();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public mainWindow() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mnOptions = new JMenu("Options");
menuBar.add(mnOptions);
JMenu mnId = new JMenu("ID");
menuBar.add(mnId);
JMenuItem idEnaItem = new JMenuItem("ID: 1");
mnId.add(idEnaItem);
idEnaItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
if(event.getActionCommand() != null){
svr.selectId(1);
setTitle("ID changed to 1");
}
}
});
JMenuItem idDvaItem = new JMenuItem("ID: 2");
mnId.add(idDvaItem);
idDvaItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
if(event.getActionCommand() != null){
svr.selectId(2);
setTitle("ID changed to 2");
}
}
});
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
messageTextField = new JTextField();
messageTextField.setBounds(10, 209, 292, 20);
contentPane.add(messageTextField);
messageTextField.setColumns(10);
JButton sendButton = new JButton("Send");
sendButton.setBounds(312, 208, 89, 23);
contentPane.add(sendButton);
sendButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
if(event.getActionCommand() != null)
{
svr.posljiSporocilo("THIS MESSAGE DOES NOT GET SENT");
}
当我从这个类调用posljiSporocilo()方法时,它会给我一个NullPointerException
}
});
}
}
我希望我给了你足够的信息,谢谢
调试模式SS:
你能告诉我为什么一开始就增加计数器吗?这将导致writerHolder数组中的第0个元素永远不会填充
userCounter++;
this.klientSocket = klientSocket;
writer = new PrintWriter(this.klientSocket.getOutputStream());
writerHolder[userCounter] = writer;
我猜你的NPE与此有关。如果您选择的id为0,那么方法posljiSporocilo中的代码将抛出NPE
但是,当我试图从包含GUI的类调用SendMessage(“someMessage”)方法时,它会给我一个NullPointerException
这是很难弄清楚的,因为你没有显示哪条线实际上抛出了NPE。在查看代码时,我看到了以下代码。我看到了writeHolder
数组的初始化位置,但我想知道writeHolder[selectedId]
是否可以null
:
public void posljiSporocilo(String message){
try {
writerHolder[selectedId].println(message);
writerHolder[selectedId].flush();
...
selectedId
是否可以大于userCounter
值?如果多个线程正在调用初始化,您可能应该使用AtomicInteger
而不是非同步的static int
我将学习使用a和单步遍历程序,查看每个对象,以查看哪个对象为空。代码中的哪一行给出了NPE?该行引用的对象可能为null?最可能的原因似乎是您试图引用PrintWriter数组中不存在的元素,从而导致NullPointerException。@11684当调用posljiSporocilo()方法并执行writerHolder[someIndex]时,您是对的cmd数组中的所有位置都为NULL,但是我不知道为什么它们为NULL,因为数组是静态的,我没有用另一个线程执行/更改writerHolder数组,而只是用类的另一个实例。为了跟踪有多少人连接。。因此,当我调用selectId(用户id)方法时,我可以将它与客户端的数量进行比较,例如:if(selectedId>userCounter){PRINT(“没有那么多用户连接”)}我的问题是,为什么一开始?将它移到我上面放的代码段的末尾,看看您是否仍然得到NPE。您总是从GUI调用默认的ServerHandler()类,您不认为您必须调用ServerHandler(Socket)构造函数吗?是的,我调用ServerHandler()构造函数,因为我不希望GUI类与套接字和java.net相关的东西有任何关系,我只是不想使用posljiSporocilo()和selectId()方法。我做了一个测试,我想知道调用posljiSporocilo()方法时userCounter的值和selectedId的值是多少,我发现当方法在构造函数中自己被调用时,这两个值都是1。但是当我从Gui类调用posljiSporocilo方法时,这两个值都是0,所以这就是导致NPE的原因。。但是我仍然不知道如何修复它。如果多个线程共享
selectId
,那么它应该是一个AtomicInteger
,正如我在@user2794550帖子中提到的那样。线程之间正在更新和共享的任何字段都必须受到保护并同步内存,但是,我没有使用另一个线程来更改值,我只是使用serverHandler类的另一个实例,因为selectId整数是静态的,所以这应该不是问题。我发现当从GUI类调用posljiSporocilo方法时,writerHolder[]数组在所有索引上都为空。我不知道如何修理它。