Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics access error

Tags:

java

generics

I could need some help with a problem I have with Java's generics. I constructed a little example for to show what I mean.

Handler

package generalizingTest;

public class Handler<S extends Server<?>> {
    public S server;

    public Handler(S server) {
        this.server = server;
    }
}

SubHandler

package generalizingTest;

public class SubHandler<S extends Server<?>> extends Handler<S> {

    public SubHandler(S server) {
        super(server);
    }

    public void subHandlerMethod() {

    }

}

Server

package generalizingTest;

import java.util.ArrayList;

public class Server<H extends Handler<?>> {
    public ArrayList<H> handlers;

    public Server() {
        handlers = new ArrayList<H>();
    }

    public void addHandler(H c) {
        handlers.add(c);
    }
}

SubServer

package generalizingTest;

public class SubServer<H extends Handler<?>> extends Server<H> {
    public void subServerMethod() {

    }
}

class diagram

Startup

package generalizingTest;

public class Startup {

    public static void main(String[] args) {
        Server<Handler<?>> serverWHandler = new Server<Handler<?>>();
        Server<SubHandler<?>> serverWSubHandler = new Server<SubHandler<?>>();

        SubServer<Handler<?>> subServerWHandler = new SubServer<Handler<?>>();
        SubServer<SubHandler<?>> subServerWSubHandler = new SubServer<SubHandler<?>>();

        Handler<Server<?>> handlerWServer = new Handler<Server<?>>(serverWHandler);
        Handler<SubServer<?>> handlerWSubServer = new Handler<SubServer<?>>(subServerWHandler);

        SubHandler<Server<?>> subHandlerWServer = new SubHandler<Server<?>>(serverWSubHandler);
        SubHandler<SubServer<?>> subHandlerWSubServer = new SubHandler<SubServer<?>>(subServerWSubHandler);

        serverWHandler.addHandler(handlerWServer);
        subServerWHandler.addHandler(handlerWSubServer);

        serverWSubHandler.addHandler(subHandlerWServer);
        subServerWSubHandler.addHandler(subHandlerWSubServer);

        subServerWHandler.subServerMethod();
        subServerWSubHandler.subServerMethod();

        handlerWSubServer.server.subServerMethod();
        subHandlerWSubServer.server.subServerMethod();

        subHandlerWServer.subHandlerMethod();
        subHandlerWSubServer.subHandlerMethod();

        System.out.println(subHandlerWSubServer.server.handlers.get(0).getClass().getName()); // SubHandler

        //produces an error:
        /*
         * Unresolved compilation problem: 
         * The method subHandlerMethod() is undefined for the type Handler<capture#9-of ?>
         */
        //subHandlerWSubServer.server.handlers.get(0).subHandlerMethod();

    }
}

I just started learning about generics. They seem to be efficient but I am not sure if I solved the problem of the generics loop () correctly with the wildcard and why those errors occur.

I really hope someone can help me out.

EDIT:

So it seems like I did not highlighted the initial problem enough. The following should be possible in any depth:

subHandlerWSubServer.server.handlers.get(0).server.handlers.get(0).server.handlers.get(0). ... .server.handlers.get(0).subHandlerMethod();

EDIT:

So this problem seems not to be solvable due to an endless loop of definition or the missing self value, see Siguza’s anwser. Here is the discussion between Siguza, user889742 and myself about this topic.

like image 556
Feirell Avatar asked Feb 17 '26 16:02

Feirell


1 Answers

If I understood you correctly, if you have a Handler<S> you want all handlers on that server to be of type Handler<S>, right?
For that, S.add() would have to only accept objects of type Handler<S>. But in order to implement that in the base class Server, you would need S, so that:

public class Server<H>
{
    public ArrayList<H<S>> handlers;

    public Server()
    {
        handlers = new ArrayList<H<S>>();
    }

    public void addHandler(H<S> c)
    {
        handlers.add(c);
    }
}

The only problem with this is that S is not defined, and you cannot easily define it. What you would need is something that, in the context of Server, means Server, and in the context of SubServer, means SubServer. Basically this.getClass(), but as a compile-time type expression. If Java had a keyword for that, say self, you could use it like this:

public class Server<H>
{
    public ArrayList<H<self>> handlers;

    public Server()
    {
        handlers = new ArrayList<H<self>>();
    }

    public void addHandler(H<self> c)
    {
        handlers.add(c);
    }
}

Then Server.add() would take Handler<Server>, and SubServer.add() would take Handler<SubServer>.

Sadly, Java has no such thing, therefore what you're trying to do is not possible this way.

Java does many things well.
Generics aren't one of them.

like image 54
Siguza Avatar answered Feb 19 '26 05:02

Siguza



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!