我有这个简单的网络代码(我正在尝试实现一个简单的聊天服务器作为练习),但我陷入困境,我无法弄清楚发生了什么。 我为我的客户端创建了GUI,它有一个另一个类的实例,它执行连接和发送/接收消息到我的服务器的所有必要操作。
package com.luca.chat;
import java.awt.*
import java.awt.event.*
import javax.swing.*
class Window extends JFrame {
private final static int WIDTH=500;
private final static int HEIGHT=300;
private String status="disconnected";
private JPanel panel;
private JTextArea area;
private JTextField field,address;
private JButton button;
private JLabel label;
private IOClass io=new IOClass(this);
Window() {
super("Chit-Chat");
setSize(new Dimension(WIDTH,HEIGHT));
ImageIcon icon=new ImageIcon("..\\images\\lucas.png");
setIconImage(icon.getImage());
JPanel contentPane=(JPanel)getContentPane();
// add the text area to display incoming and outgoing messages
area=new JTextArea();
area.setEditable(false);
contentPane.add(area,BorderLayout.CENTER);
// add text field to send messages
field=new JTextField(20);
field.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
String message=field.getText();
io.send(message);
field.setText("");
}
});
panel=new JPanel();
panel.add(field);
panel.setBorder(BorderFactory.createEtchedBorder());
contentPane.add(panel,BorderLayout.SOUTH);
// add status bar on top
label=new JLabel("status: "+status);
address=new JTextField(15);
button=new JButton("connect");
panel=new JPanel();
panel.add(label);
panel.add(address);
panel.add(button);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
io.connect(address.getText());
}
});
panel.setBorder(BorderFactory.createEtchedBorder());
contentPane.add(panel,BorderLayout.NORTH);
Toolkit kit=getToolkit();
Dimension dim=kit.getScreenSize();
setLocation((dim.width-WIDTH)/2,(dim.height-HEIGHT)/2);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
loop();
}
void loop() {
while (true)
if (io.connected)
io.receive();
else // if I comment this line out it never calls receive() ?????
System.out.println("????");
}
void setStatus(String status) {
label.setText(status);
}
void setText(String received) {
area.append(received);
}
public static void main(String[] args) {
new Window();
}
}
IOClass有连接/发送/接收的所有方法(我认为它的作用类似于控制器?我不知道,我只是开始学习这种模式)一个标志,它控制是否连接是否建立。 如果有连接,它会调用receive方法,这是一个无限循环来监听传入的消息。
但是如果我只留下if语句(内部循环())没有别的......它就不会执行!我的意思是.. while循环永远不会开始(我尝试了一些打印件......它永远不会到达那里)但是如果我添加了其他的话它会到达那里!
例如,阻塞if语句:
void loop() {
while (true)
if (io.connected)
io.receive();
}
这是有效的(while循环永远):
void loop() {
while (true)
if (io.connected)
io.receive();
else
....do something else...
}
甚至可行:
void loop() {
while (true) {
System.out.println("whatever");
if (io.connected)
io.receive();
} // end of while
}
我无法理解,这对我来说似乎是一种非常奇怪的行为。
编辑:使用Eclipse的调试功能我看到,当它工作时,while循环会按预期永久循环,当它不存在时,它只是在if条件下阻塞
答案 0 :(得分:0)
void loop() {
while (true)
if (io.connected)
io.receive();
else // if I comment this line out it never calls receive() ?????
System.out.println("????");
}
在你的答案的例子中,你指出这个代码是罪魁祸首。由于while
没有括号{}
,因此只有下一行才会被视为while循环的主体。 if
没有括号也是如此:只有真实条件中的第一行才会执行。它可能会或可能不会跟随else
- 条款。
在您的情况下,由于while
之后的下一行是if-else
且两个条件只有一行要执行,因此您的while循环按预期工作。
如果您的意思是:
void loop() {
while (true)
if (io.connected)
io.receive();
//else
System.out.println("????");
}
然后这不会编译,因为你告诉System.out.println("????");
执行 AFTER while循环完成并且while循环的条件显式为true;永远不会达到代码。如果您使用变量作为标志,它将进行编译,当循环完成时,您将体验System.out.println("????");
将执行一次。
答案 1 :(得分:0)
在Eclipse调试器的帮助下,一步一步地,我找到了捕获。 因为当我实例化JFrame时,JVM会自动旋转一个新线程(Event队列),因为它是使用连接按钮注册的ActionListener,它调用将boolean标志设置为true的connect()方法,标志为true在这一个线程中,但是在主线程中它仍然是假的,所以if条件永远不会计算为true,因此,我挂起等待调用receive()方法,并且我在屏幕上没有输出。 使用volatile修饰符可以解决问题,因此更新的变量对所有线程都是自动可见的。 由于我是新手,所以这并不是那么明显......但是评论让我朝着正确的方向前进。