简体   繁体   中英

Why does java complain when I rethrow SocketException to be caught by IOException?

The general rule of exceptions is that you catch more specific ones before catching general ones. I have a case where closing a server throws SocketException: socket closed coming from my listener which is caught by IOException , but I don't want to show the user that message when they close the server. Everything else is probably an actual error so it should be shown to them, so I catch SocketException , check its message and if it is not socket closed then it should be rethrown to be caught and handled as an IOException . Java/NetBeans 7.0.1 do not seem to like that. Here is my code:

public void run() {
        while (runner == Thread.currentThread()) {
            System.out.println("waiting for connection...");
            try {
                Socket s = server.accept(); //throws SocketException/IOException
                if (session == null) {
                    session = new ReceiveSession(s, parent);
                } else {
                    s.close();
                }
            } catch (SocketException e) {
                if (!e.getMessage().equals("socket closed")) {
                    throw e; //error line, "unreported exception SocketException"
                }
            } catch (IOException e) {
                e.printStackTrace();
                parent.showError("Someone tried to connect but the connection failed: " + e);
                session = null;
            }
        }

    }

When trying to clean and build, I get:

error: unreported exception SocketException; must be caught or declared to be thrown
                throw e;
1 error

Since SocketException extends IOException , it should be caught by the more general IOException . Why do I get this error? (Running the project as is in NetBeans works perfectly btw, it doesn't show the user the exception when the server shuts down as I want.)

您的throwtry之外 ,因此,下面的catch不会处理引发的异常。

The second catch will not catch the rethrow since it wasn't thrown in the try block for which the second catch is responsible. You'll need to restructure the code.


For example, the most straight forward restructuring would be this:

public void run() {
    while (runner == Thread.currentThread()) {
        System.out.println("waiting for connection...");
        try {
            try {
                Socket s = server.accept(); //throws SocketException/IOException
                if (session == null) {
                    session = new ReceiveSession(s, parent);
                } else {
                    s.close();
                }
            } catch (SocketException e) {
                if (!e.getMessage().equals("socket closed")) {
                    throw e; //error line, "unreported exception SocketException"
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            parent.showError("Someone tried to connect but the connection failed: " + e);
            session = null;
        }
    }
}

The nested tries make me cry a little, but it would get the job done (and to be honest, off the top of my head, I can't think of a better way that doesn't go way too far).

Catch statements catch exceptions from their respective try block, not from other catch blocks in the list. You're throwing the exception from outside the try, so it does not get caught by subsequent catch blocks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM