I'm trying to figure out how to structure a program using Java's generics, and wondering if I am doing something fundamentally wrong or just missing a simple bug in my code.
Say I have a generic class:
public interface Handler<T>{
public void process(T t);
}
Another generic class takes Handler as a generic parameter (pseudo code):
public int开发者_运维知识库erface Processor<S extends Handler<T>>{ //<== Error: cannot find symbol 'T'
public void addHandler(S u);
public void process(T t);
}
Abstract implementation providing boiler-plate implementations
public abstract class ProcessorImpl<.....> implements Processor<.....>{
...
}
Think of a processor as an object that dispatches requests to process data to any number of handlers. Specific instances can be variations of process pipelines, intercepting filters, event systems, etc.
I'd like to be able to use it like the following:
Handler<String> myHandler1 = new HandlerImpl<String>();
Handler<String> myHandler2 = new HandlerImpl<String>();
Handler<Integer> myHandler3 = new HandlerImpl<Integer>();
Processor<Handler<String>> proc = ProcessorImpl<Handler<String>>();
proc.addHandler(myHandler1);
proc.addhandler(myHandler2);
proc.addhandler(myHandler3);//this should be an error!
I can't get it to work. On paper it looks like it should be trivial, any ideas?
Thanks
So each type parameter is only defined within the class, thus T
isn't defined or available in Processor
class.
You probably want to have Processor
be:
public interface Processor<T>{
public void addHandler(Handler<? super T> u);
public void process(T t);
}
Here you are declaring a Processor
that can only handle events/input of a particular type, e.g. String
, Integer
, etc. So the following statement will be valid:
Processor<String> proc = ...
proc.addHandler(new Handler<String>()); // valid
proc.addHandler(new Handler<Object>()); // valid, as Strings are Objects too
proc.addHandler(new Handler<Integer>()); // invalid, not a String handler
proc.process("good"); // valid
proc.process(1); // invalid, not a String
If Processor
is intended to handle types at runtime and makes a dynamic dispatch based on the appropriate runtime type, then you can declare proc
(in the last example) as Processor<?>
. Then all the statements are valid.
These changes should work:
public interface Processor<T, S extends Handler<T>>
and
class ProcessorImpl<T, S extends Handler<T>>
implements Processor<T, S>
and
Processor<String, Handler<String>> proc = new ProcessorImpl<String, Handler<String>>();
It shouldn't work, as your T=String and handlers of integers are not allowed. At compile time, your class will have method process(String t) and not process(Integer t).
精彩评论