#java #class #variables #null #printwriter
#java #класс #переменные #null #printwriter
Вопрос:
Я новичок в программировании, и мне нужна помощь с этим небольшим препятствием. Я создаю простую программу чата с сервером и клиентом чата. Итак, мой клиент запускается и просто отлично создает сетевое соединение, которое включает в себя PrintWriter
, которое отправляет на мой сервер. Затем, в другом классе (моем ActionListener
), когда я вызываю переменную writer, она становится недействительной с помощью NullPointerException
.
Итак, я пытался вызывать setupnetworking при каждом запуске ActionListener, но в итоге они подключаются ко многим соединениям, и мое сообщение распечатывается более одного раза. Могу ли я сохранить setupnetworking в моем main()
методе и сохранить значение переменной PrintWriter
для моего ActionListener
класса. Извините, если я что-то путаю, поэтому, пожалуйста, посмотрите на мой код и скажите мне, что вы думаете.
Вот вся программа…
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class SimpleChatClient {
BufferedReader reader;
PrintWriter writer;
Socket sock;
JTextArea chatbox = new JTextArea(10,20);
JTextField entertext = new JTextField(20);
JButton sendchat = new JButton("send");
public void go(){
setUpNetworking();
Thread readerThread1 = new Thread(new IncomingReader());
readerThread1.start();
//big probelm. to many setUpNetworkings!!!!!!!!
}
public class SendButtonListener implements ActionListener{
public void actionPerformed (ActionEvent ev){
try {
writer.println(entertext.getText());
writer.flush();
System.out.println("chat flush");
}
catch (Exception ex) {
ex.printStackTrace();
System.out.println("action fail");
}
entertext.setText("");
entertext.requestFocus();
}
}
public void setUpNetworking() {
try {
sock = new Socket("192.168.0.11", 65534);
InputStreamReader streamReader =
new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamReader);
writer = new PrintWriter(sock.getOutputStream(), true);
System.out.println("network established. Beginning mainstream feed.");
}
catch (IOException ex) {
ex.printStackTrace();
System.out.println("setup fail");
}
}
public class IncomingReader implements Runnable {
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " message);
chatbox.append(message "n");
chatbox.append("n");
}
}catch (Exception ex) {
ex.printStackTrace();
System.out.println("run fail");
}
}
}
}
P.s для этого у меня тоже есть программа с графическим интерфейсом. Это просто устанавливает соединение.
Комментарии:
1. откуда вы знаете, что значение writer равно null — вы выполнили операцию в отладчике или добавили дамп в System.out?
2. да, у меня есть, это всего лишь версия без связки System.out.print
3. Печатается ли оно
"network established... "
?4. да, оба моих сервера-клиента печатают, что соединение было защищено.
5. я предполагаю, что writer — это поле класса-владельца?, было бы полезно показать класс верхнего уровня и его поля. Не обязательно показывать все методы.
Ответ №1:
Это может быть проблема с инициализацией памяти с несколькими потоками. Если writer
поле считывается в EDT до его инициализации, то оно может не быть повторно прочитано в этом потоке при инициализации в вашем основном потоке.
В качестве быстрого теста добавьте volatile
в объявление writer
.