Caleb Huggins
Caleb Huggins

Reputation: 89

unhandled exception: IOException must be caught or thrown

So recently I have started work on my own IRC client/server in Java. NetBeans is saying that I have an unhandled IOException. However, looking at my code I do a try-catch block that catches the IOException. Here is my code:

package some.package.name;


import java.io.IOException;
import java.net.ServerSocket;

public class IRCServer extends ServerSocket {

    private ServerSocket server;
    private int port;

    /**
     * <p>Main constructor. Provides default port of 6667</p>
     */
    public IRCServer() {
        this(6667);
    }

    /**
     * <p>Secondary constructor. Uses port defined by either user or Main constructor</p>
     *
     * @param port The port to listen to for the server
     */
    public IRCServer(int port) { //This is where NetBeans show the error
        this.port = port;
        try {
            server = new ServerSocket(port);
        } catch (IOException e) {
            System.err.println("IOException caught\n" + e.toString());
        }
    }

    /**
     * <p>Overrides parent String toString()</p>
     *
     * @return PORT the server is listening to
     */
    @Override
    public String toString() {
        return "PORT: " + this.port;
    }
}

Note that the IOException in the try...catch is, indeed, java.io.IOExecption.

What is causing the compilation error?

EDIT: I have tried the same code in both Eclipse and by compiling it via cmd. It is still giving the same error

Upvotes: 0

Views: 581

Answers (1)

RealSkeptic
RealSkeptic

Reputation: 34618

Your problem is that your class both extends ServerSocket and has a ServerSocket field. This means that for every instance of IRCServer you theoretically have two ServerSocket instances. One is the IRCServer itself, because it extends it, and one is the embedded ServerSocket you named server.

This in itself is a serious design problem - there is no need to extend a class if you are not actually relying on its original functionality in any way. And if you intended to use the IRCServer as a ServerSocket, you shouldn't have an additional one embedded in. this becomes your server.

But the issue that causes the compilation error is the fact that every constructor implicitly or explicitly calls the super() constructor. If the original class had a no-args constructor - and it does - then if you fail to call super(...) yourself, it will be done for you.

However, the constructors of ServerSocket are declared as:

public ServerSocket() throws IOException

and

public ServerSocket(int port) throws IOException

This means that the implicit call to the super() constructor happens right before your try...catch, and it throws a checked exception. It means that you have to declare your own constructor as throws IOException, as there is no way to surround a super() call with try...catch.

My advice would be either to extend the class properly or delegate without extending. Properly extending means no server variable. And your constructors would look like:

/**
 * <p>Main constructor. Provides default port of 6667</p>
 */
public IRCServer() throws IOException {
    this(6667);
}

/**
 * <p>Secondary constructor. Uses port defined by either user or Main constructor</p>
 *
 * @param port The port to listen to for the server
 */
public IRCServer(int port) throws IOException {
    super(port);
    this.port = port;
}

And properly delegating would mean keeping most of your original code but removing the extends ServerSocket, and then you will not be able to use IRCServer polymorphically as a ServerSocket.

Upvotes: 1

Related Questions