У меня есть проблема, которую я пытаюсь выяснить в течение нескольких дней.
Простой обзор кода (псевдокод):
1 - Когда пользователь подключается, создайте для него PrintWriter.
2 - Сохраните объект PrintWriter в массиве PrintWriter[].
3 - Увеличьте количество подключенных пользователей.
В чем моя проблема?
- Компилятор выдает исключение NullPointerException.
Что вызвало НЭП?
Когда метод sendMessage() вызывается объектом, созданным в классе mainWindow, массив PrintWriter, если он пуст, я не знаю, что заставляет его быть пустым, поскольку все переменные и массивы имеют статические модификаторы, а массив PrintWriter[] получает значение в конструкторе (когда пользователь подключается).
Внутри конструктора ServerHandler, когда я пытаюсь отправить сообщение клиенту, он работает нормально, и я вижу, что массив PrintWriter[] не пуст, но когда я вызываю метод sendMessage() из экземпляра mainWindow, массив пуст и Целочисленная переменная userCounter по-прежнему равна 0.
Что я пытался исправить?
- Установка переменных и модификаторов массива на volatile и static.
- Написание всего кода с нуля снова и снова.
Класс сервера (отлично работает):
package homeControl;
import java.net.*;
import java.util.Scanner;
import java.io.*;
import java.awt.*;
public class Server{
String sporocilo = null;
int id = 0;
outputHelper o = new outputHelper();
public void sprejmiPovezavo()
{
try
{
ServerSocket svrSock = new ServerSocket(5000);
while(true){
Socket klientSocket = svrSock.accept();
new Thread(new ServerHandler(klientSocket)).start();
}
}catch(IOException ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args){
Server svr = new Server();
svr.sprejmiPovezavo();
}
}
Класс ServerHandler (этот класс вызывает проблемы)
package homeControl;
import java.net.*;
import java.util.ArrayList;
import java.io.*;
import java.awt.*;
public class ServerHandler implements Runnable{
static PrintWriter pw;
static PrintWriter[] writerHolder = new PrintWriter[10];
static int userCounter;
static int selectedID;
public ServerHandler(Socket socket){
try{
pw = new PrintWriter(socket.getOutputStream());
writerHolder[userCounter] = pw;
// Testing if this writerHolder[] can send the message to the client.
writerHolder[userCounter].println("autoSent - Testint!");
writerHolder[userCounter].flush();
userCounter++;// Increment the number of people connected
//Testing the values of the variables.
System.out.println("ORG!\nuserCounter:" + userCounter + "\nwriterHolder[userCounter]" + writerHolder[0]);
}catch(Exception ex)
{
ex.printStackTrace();
}
}
public ServerHandler()
{
// Empty constructor
// Used so that i don't need to pass a Socket into the class when i create a ServerHandler object from the mainWindow.class...
}
public void sendMessage(int tempID, String messageToBeSent)
{ // Testing the values of variables at the time that this method gets called.
System.out.println("tempID:" + tempID + "\n" + "messageToBeSent:" + messageToBeSent + "\n" + "userCounter:" + userCounter + "\n" + "selectedID:" + selectedID);
// End of test/Actual code:
writerHolder[tempID].println(messageToBeSent);
writerHolder[tempID].flush();
}
public void run()
{
}
}
класс mainWindows (где вызывается метод sendMessage())
package homeControl;
import java.awt.*;
import java.io.*;
import java.net.Socket;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JTextField;
import javax.swing.JButton;
public class mainWindow extends JFrame {
private JPanel contentPane;
private JTextField messageTextField;
ServerHandler svr = new ServerHandler(); // Thats why i use the empty constuctor in ServerHandler.class.
outputHelper o = new outputHelper();
int ID;
/**
* 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: 0");
mnId.add(idEnaItem);
JMenuItem idDvaItem = new JMenuItem("ID: 1");
mnId.add(idDvaItem);
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)
{ // Calling the sendMessage() in the ServerHandler.class which should send a message to the Client.
svr.sendMessage(ID,messageTextField.getText());
}
}
});
}
}
Вывод конструктора ServerHandler при тестировании PrintWriters:
ОРГ!
счетчик пользователей: 1
WriterHolder[userCounter]java.io.PrintWriter@798c668c
Выход из метода SendMessage, когда я вручную пытаюсь отправить сообщение:
сообщениеToBeSent:dsda
пользовательский счетчик: 0
выбранныйID:0
ОШИБКА:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at homeControl.ServerHandler.sendMessage(ServerHandler.java:45)
at homeControl.mainWindow$2.actionPerformed(mainWindow.java:84)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
PrintWriter
будет использоваться. Где он устанавливается? Я не мог найти его. Возможно, вы пытаетесь получить доступ к позиции в вашем массиве, которая еще не была установлена. - person Mauren   schedule 20.09.2013