Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics method parameter passing issue

Tags:

java

generics

I have a problem about passing an parameter to a generic method. The code is the following:

public class View<T extends View<T,PM>, PM extends Source>  {

    protected PM source;
    protected EventManager<T, PM> eventManager;

    public View(PM s){
        this.source = s;
        eventManager = new EventManager<T, PM>();
        eventManager.setTarget(this); //error: "The method setTarget(T) in the type
                              //EventManager<T,PM> is not applicable for the arguments (View<T,PM>)"

        eventManager.setSource(s);
    }

    public void setBinding(Topic topic, IEventAction<T,PM> action){
        eventManager.setEventAction(topic, action)
    }

}

/** 
* EventManager class has to remain completely generic. The type parameters cannot "extends"
* anything because the EventManager is used also in other parts where T and S will have to be
* classes other than "View" and "Source"
*/
public class EventManager<T, S> {
    protected T target;
    protected S source;
    private LinkedHashMap<Topic, IEventAction<T, S>> eventActions;

    public EventManager(T target, S source){
        this.target = target;
        this.source = source;
    }

    public void setTarget(T target){
        this.target = target;
    }

    public void setSource(S source){
        this.source = source;
    }

    public void setEventAction(Topic topic, IEventAction<T, S> action) {
        //some code here ...
        omissis...

        eventActions.put(topic, action);

        omissis...
    }

    //other methods down here...omissis
}

Eclipse gives me the error I put in comment on the line "eventManager.setTarget(this);". I can't understand why it gives me this error. Anyway, I found a solution (apparently) but I am not sure whether I did a "clean" or "dirty" thing. The solution is this:

 eventManager.setTarget((T)this);

but it gives me a warning: "Type safety: Unchecked cast from View to T". To elimitate the warning I also put the following on top of the constructor method:

@SuppressWarnings("unchecked")

It seems working but what is wrong? Do you have another "cleaner" solution (if it exists)? Do you think this is a "dirty" approach?

Any soggestions are very welcome.

like image 699
user1085876 Avatar asked Feb 22 '23 04:02

user1085876


1 Answers

The error occurs because you are instantiating EventManager with T, which can be any subclass of View at runtime, but you are passing exactly View (known at compile time). Since normally you cannot pass a superclass when a subclass is required, your code does not compile.

The solution (without changing the code) is of course to cast the superclass to the subclass (which is what you are doing) and try your best not to get a ClassCastException.

If you are sure that you will never pass incompatible types, then it's ok I guess (though very confusing). Maybe try to redesign it somehow.

like image 74
Tudor Avatar answered Mar 05 '23 03:03

Tudor