0

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 interface 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

3
  • you say '//error!'. Do you mean you would like it to be an error? Or that the compiler is issuing an error that you want to avoid? Commented Nov 29, 2009 at 5:43
  • Sorry, I should have been clearer. The "//error!" on the last line is expected. I want that to the an error. Commented Nov 29, 2009 at 6:29
  • Great. Then my answer below is actually relevant to the question! Commented Nov 29, 2009 at 7:12

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Why not public void addHandler(Handler<T> u);
@Harold, this works too, yet it's a bit restrictive. Having addHandler accept Handler<T> prevents Processor<String> from accepting Handler<Object>, and this should be valid. Imagine a LoggerHandler<Object> that simply prints the argument. You should be able to pass it to any processor I think.
1

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>>();

Comments

0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.