Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java - How to create an instance of generic type T

Tags:

java

generics

I am writing a server like below

public class Server<T extends RequestHandler> {

    public void start() {

        try{
            this.serverSocket = new ServerSocket(this.port, this.backLog);
        } catch (IOException e) {
            LOGGER.error("Could not listen on port " + this.port, e);
            System.exit(-1);
        }

        while (!stopTheServer) {
            socket = null;
            try {
                socket = serverSocket.accept();
                handleNewConnectionRequest(socket);
            } catch (IOException e) {
                LOGGER.warn("Accept failed at: " + this.port, e);
                e.printStackTrace();
            }
        }

    }

    protected void handleNewConnectionRequest(Socket socket) {
        try {
            executorService.submit(new T(socket));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

But in the handleNewConnectionRequest(...) method, I can't create an instance of T as it is actually not a class. Also I can't use the method mentioned here as I want to pass the socket instance so that the request handler can get OutputStream and InputStream on the socket.


Can't I make a generic server like above and have different protocol handlers e.g

public class HttpRequestHandler extends RequestHandler {
    ...
}

public class FtpRequestHandler extends RequestHandler {
    ...
}

public class SmtpRequestHandler extends RequestHandler {
    ...
}

and then use them like below

Server<HttpRequestHandler> httpServer = new Server<HttpRequestHandler>();
Server<FtpRequestHandler> ftpServer = new Server<FtpRequestHandler >();
Server<SmtpRequestHandler> smtpServer = new Server<SmtpRequestHandler >();
like image 739
Yatendra Avatar asked Oct 28 '11 19:10

Yatendra


3 Answers

You'll need an instance of the class. The generic type T isn't enough. So you'll do:

class Server <T extends RequestHandler> {
    Class<T> clazz;
    public Server(Class<T> clazz) {
        this.clazz = clazz;
    }

    private T newRequest() {
        return clazz.newInstance();
    }
}
like image 137
Kevin Avatar answered Oct 21 '22 11:10

Kevin


Maybe make different Server subclasses befitting various handler types. One example:

public class HttpServer extends Server<HttpRequestHandler> {

    protected HttpRequestHandler wrapSocket(Socket socket) {
        return new HttpRequestHandler(socket);
    }

}

And adapt Server like so:

public abstract class Server<T extends RequestHandler> {

    protected abstract T wrapSocket(Socket socket);

    protected void handleNewConnectionRequest(Socket socket) {
        try {
            executorService.submit(wrapSocket(socket));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Just a thought...

like image 42
G_H Avatar answered Oct 21 '22 12:10

G_H


You don't. It doesn't make sense. In this case I'd probably avoid generics. Plain old interface or abstract class does job. You can make abstract server with abstract factory method.

abstract class Server {
    abstract protected RequestHandler newRequest(Socket socket);
    ... same as before
}
like image 1
viktor Avatar answered Oct 21 '22 11:10

viktor