Java 爪哇Swing&;套接字通讯器堆栈溢出错误

Java 爪哇Swing&;套接字通讯器堆栈溢出错误,java,swing,sockets,stack-overflow,Java,Swing,Sockets,Stack Overflow,我正在使用套接字和JSwing制作一个简单的客户机-服务器messenger对,最近遇到了一个StackOverflow错误。我知道(或至少认为)它是由一个递归函数(我认为我没有,但我可能有)引起的,该函数没有正确的终止条件(这是否意味着类似于switch语句中的返回;) 下面是一些错误(因为这是堆栈溢出,当然它会重复自身) } ClientSwing: public class ClientSwing extends JFrame implements Runnable { public So

我正在使用套接字和JSwing制作一个简单的客户机-服务器messenger对,最近遇到了一个StackOverflow错误。我知道(或至少认为)它是由一个递归函数(我认为我没有,但我可能有)引起的,该函数没有正确的终止条件(这是否意味着类似于switch语句中的
返回;
) 下面是一些错误(因为这是堆栈溢出,当然它会重复自身)

}

ClientSwing:

public class ClientSwing extends JFrame implements Runnable {
public SocketManager socketmanager = new SocketManager();

public final int NULL = 0;
public final int DISCONNECTED = 1;
public final int DISCONNECTING = 2;
public final int BEGIN_CONNECT = 3;
public final int CONNECTED = 4;
public int connectionStatus = socketmanager.connectionStatus;

public JPanel panel, statusBar;
public JTextArea textArea;
public JTextField textField, statusColor, usernameField;
public JLabel statusField;
public JMenuBar menuBar;
public JButton connectButton, disconectButton;

public int WIDTH = 640;
public int HEIGHT = 480;

public ClientSwing() {
    super("Client");

    panel = new JPanel();
    panel.setLayout(null);



    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setSize(WIDTH, HEIGHT);
    setResizable(true);
    setJMenuBar(menuBar);
}

@Override
public void run() {
    switch(connectionStatus) {
    case DISCONNECTED:

        break;

    case DISCONNECTING:

        break;

    case CONNECTED:

        break;

    case BEGIN_CONNECT:

        break;
    }
}

public void invoke(Runnable runnable) {
    SwingUtilities.invokeLater(runnable);

}
}

SocketManager:

public class SocketManager extends JFrame implements Runnable {
public ClientSwing cs = new ClientSwing();

public final int NULL = 0;
public final int DISCONNECTED = 1;
public final int DISCONNECTING = 2;
public final int BEGIN_CONNECT = 3;
public final int CONNECTED = 4;

public final String statusMessages[] = {
    " Error! Could not connect", " Disconnected",
    " Disconnecting...", " Connceting...", " Connected"
};

public final String END_CHAT_SESSION = new Character((char)0).toString();

public String hostIP = "localhost";
public int port = 2484;
public int connectionStatus = DISCONNECTED;
public StringBuffer toAppend = new StringBuffer("");
public StringBuffer toSend = new StringBuffer("");
public String statusString = statusMessages[connectionStatus];

public Socket socket;
public BufferedReader in;
public PrintWriter out;

public String error;

//Make a method that gets the username from the username field
public String username = "username"; 

public void changeStatusNTS(int newConnectStatus, boolean noError) {
    if(newConnectStatus != NULL) {
        connectionStatus = newConnectStatus;
    }

    if(noError) {
        statusString = statusMessages[connectionStatus];

    } else {
        statusString = statusMessages[NULL];

    }

    SwingUtilities.invokeLater(cs);
}

public void changeStatusTS(int newConnectStatus, boolean noError) {
    if(newConnectStatus != NULL) {
        connectionStatus = newConnectStatus;
    }

    if(noError) {
        statusString = statusMessages[connectionStatus];

    } else {
        statusString = statusMessages[NULL];

    }

    cs.run();
}

public void cleanUp() {

}

private void appendToChatBox(String s) {
    synchronized(toAppend) {
        toAppend.append(s);
    }
}

private void sendString(String s) {

}

@Override
public void run() {
    while(true) {
        try {
            Thread.sleep(10);

        } catch(InterruptedException e) {
            error = e.toString();
            //Append the error to the textArea
        }

        switch(connectionStatus) {
        case BEGIN_CONNECT:
            try {
                socket = new Socket(hostIP, port);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //I AM RIGHT HERE
                out = new PrintWriter(socket.getOutputStream(), true);
                changeStatusTS(CONNECTED, true);

            } catch(Exception e) {
                cleanUp();
                changeStatusTS(DISCONNECTED, false);

                error = e.toString();

            }

            break;

        case CONNECTED: 
            try {
                if(toSend.length() != 0) {
                    out.print(toSend);
                    out.flush();
                    toSend.setLength(0);
                    changeStatusTS(NULL, true);
                }

                if(in.ready()) {
                    String input = in.readLine();
                    if((input != null) && (input.length() != 0)) {
                        if(input.equals(END_CHAT_SESSION)) {
                            changeStatusTS(DISCONNECTING, true);

                        } else {
                            appendToChatBox(username + ": " + input + "\n");
                        }
                    }
                }
            }  catch(IOException e) {
                cleanUp();
                changeStatusTS(DISCONNECTED, false);

                error = e.toString();
            }
            break;

        case DISCONNECTING:
            out.print(END_CHAT_SESSION);
            out.flush();

            cleanUp();
            changeStatusTS(DISCONNECTED, true);

            break;

        default: break; //do nothing
        }
    }
}

class ActionAdapter implements ActionListener {
    public void actionPerformed(ActionEvent e) {}
}

}

正因为如此,您将获得一个
堆栈溢出

public class SocketManager extends JFrame implements Runnable {
    public ClientSwing cs = new ClientSwing();
....

public class ClientSwing extends JFrame implements Runnable {
    public SocketManager socketmanager = new SocketManager();
您正在创建一个
ClientSwing
,它创建一个
SocketManager
,它创建一个
ClientSwing
,它创建一个
ClientSwing
,它创建一个
SocketManager
,它创建一个
ClientSwing
,它创建一个
SocketManager
,创建
ClientSwing
,创建
SocketManager
,创建
ClientSwing
,创建
SocketManager
,创建
ClientSwing
,创建
SocketManager
,创建
ClientSwing
,创建
SocketManager
,这创造了一个
堆栈溢出

明白了吗

  • 如果您想要访问另一个类,不要实例化它。可以将一个类作为引用传递给另一个类。并为要访问的字段提供适当的getter和setter
  • 或者,您可以创建MVC设计,这是在类之间共享数据的更合适的方式
旁注

  • 看看

编辑

像这样的事情将是明确的可能性。不是实例化,而是按值传递

public class ClientSwing ...{
    SocketManager socketManager;
    public ClientManger(SocketManager socketManger) {
        this.socketManage = socketManager;
    }
}

非常感谢您的快速回复!我不是想表现得粗鲁,我真的很感谢你的帮助,但是我如何使用多个JFrames/它如何适用于这种情况?当然,无论如何我都在读这篇文章。还有,解决我问题的方法是什么?我想把我必须从其中一个类调用的变量作为静态变量,这样我就不必实例化(正确使用这个词?)SocketManager类,我只需执行
SocketManager.connectionStatus
。这样行吗?再次感谢您的帮助查看我的更新。此外,您正在使用多个
JFrame
s,但这不是问题所在。正如你所看到的,这只是一个旁注。只是一个友好的建议。当你指的是JFrames时,你不是在说JPanels,对吧?我实际上指的是
ClientMain
ClientSwing
SocketManager
哦,我明白你的意思了。我拥有这些扩展JFrame的唯一原因是,我可以在SocketManager类中使用
SwingUtilities.invokeLater()
。有更好的方法吗?
public class SocketManager extends JFrame implements Runnable {
    public ClientSwing cs = new ClientSwing();
....

public class ClientSwing extends JFrame implements Runnable {
    public SocketManager socketmanager = new SocketManager();
public class ClientSwing ...{
    SocketManager socketManager;
    public ClientManger(SocketManager socketManger) {
        this.socketManage = socketManager;
    }
}