Iterate over specific instances in a List - java

I have an ArrayList witch constains some instances of different classes ,I want to iterate over a specific type of classes(for example classes tha extend OnRender.class) in a for loop;
I have a working code but the code breaks the OO rules resulting in some warnings.
Can I make this happen or I will be always break OO by downcasting.
Looking back at what I wrote ,I see that I didnt explained it very good ,so check the code below to see what I mean
the code:
public class ListenerManager{
List<Object> listeners=new ArrayList<Object>();
int it;
Class clazz;
public <T extends Object> T begin(Class<T> clazz){
it=-1;
this.clazz=clazz;
return next();
}
public <T extends Object> T next(){
while((++it)<listeners.size()){
if (clazz.isInstance(listeners.get(it))){
return (T)listeners.get(it);
}
}
return null;
}
public void add(Object listener){
listeners.add(listener);
}
}
I use it like that:
ListenerManager lm=new ListenerManager();
lm.add(new OnRenderListener(){
........
});
for(OnRenderListener orl=lm.begin(OnRenderListener.class);orl!=null;orl=lm.next){
.......
}
the warning I get:
Class clazz; -> Class is a raw type. References to generic type Class should be parameterized
return (T)listeners.get(it); -> Type safety: Unchecked cast from Object to T
I don't want to suspend the warnings with just a Suspecnd annotation,I want to follow the OO rules.

If you want to identify particular classes or interfaces, use instanceof:
for (Object o : listeners) {
if (o instanceof X) {
X x = (X)o;
}
}
However this isn't very good at all. You really want to leverage the inheritance and polymorphism of the language. My first thought is that your list should container only Listeners or subtypes e.g.
listeners = new ArrayList<Listener>();
and then you don't require the cast. Everything you pull out from the list will be a Listener (or subtype) and typed as such:
for (Listener l : listeners) {
// listener type functionality here...
}
The Visitor pattern is an option here too. You could pass your visitor object into each listener, and each listener would decide what to do based on its type. The advantage is that as you add subtypes you have to add the appropriate methods - there's no danger of omitting a type from a sequence of class declarations.
Visitor v = new OnlyInterestedInOneTypeOfListener();
for (Listener l : listeners) {
l.useVisitor(v); // different subclasses will call different methods
// on the visitor. Some may be no-ops for different visitor
// implementations
}
(as an aside, I note that you want to discover entries that implement a particular method. This is called duck-typing, and Java doesn't support it. Other languages such as Scala do)

You can use Guava's Iterables.filter() method. It will iterate only on the subtype you want.
for (YourType filteredElement : Iterables.filter(listeners, YourType.class)) {
doSomething(filteredElement);
}

Your ListenerManager should either return a java Iterator, or a filtered Collection (or List). Don't rebuild a iterator concept on your own. Especially having a begin and next on your manager class will introduce unnecessary states there.
With Java 8, your ListenerManager can easily be writte as:
public class ListenerManager {
private final List<Object> listeners = new ArrayList<Object>();
public <T> Collection<T> listenersOf(Class<T> type) {
return listeners.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}
public void add(Object listener) {
listeners.add(listener);
}
}
If you use a Java version prior to 8, use a good-old for-each instead:
public <T> Collection<T> listenersOf(Class<T> type) {
List<T> result = new ArrayList<T>();
for (Object l : listeners) {
if (type.isInstance(l)) result.add(type.cast(l));
}
return result;
}

This is only a rough (not compilable) way I would do it
public interface Listener{
public boolean canHandle(Event ev);
public void handle(Event ev);
}
public class OnRenderListener implements Listener {
public boolean canHandle(Event ev){
return ev instanceOf OnRenderEvent; // or look for the classname
}
public void handle(Event ev);
}
public class KeyPressListener implements Listener {
public boolean canHandle(Event ev){
return ev instanceOf KeyPressEvent; // or look for the classname
}
public void handle(Event ev){
keyPressed(((KeyPressEvent)ev).getKey());
}
keyPressed(int key){....}
}
public class Event{}
public class KeyPressEvent extends Event{
int key;
}
public class OnRenderEvent extends Event{
//other stuff
}
//Loop to fire an event
for(Listener lis : listeners){
if(lis.canHandle(currentEvent){
lis.handle(currentEvent);
}
}

Related

Can I define the Negatable interface in Java?

Asking this question to clarify my understanding of type classes and higher kinded types, I'm not looking for workarounds in Java.
In Haskell, I could write something like
class Negatable t where
negate :: t -> t
normalize :: (Negatable t) => t -> t
normalize x = negate (negate x)
Then assuming Bool has an instance of Negatable,
v :: Bool
v = normalize True
And everything works fine.
In Java, it does not seem possible to declare a proper Negatable interface. We could write:
interface Negatable {
Negatable negate();
}
Negatable normalize(Negatable a) {
a.negate().negate();
}
But then, unlike in Haskell, the following would not compile without a cast (assume MyBoolean implements Negatable):
MyBoolean val = normalize(new MyBoolean()); // does not compile; val is a Negatable, not a MyBoolean
Is there a way to refer to the implementing type in a Java interface, or is this a fundamental limitation of the Java type system? If it is a limitation, is it related to higher-kinded type support? I think not: it looks like this is another sort of limitation. If so, does it have a name?
Thanks, and please let me know if the question is unclear!
Actually, yes. Not directly, but you can do it. Simply include a generic parameter and then derive from the generic type.
public interface Negatable<T> {
T negate();
}
public static <T extends Negatable<T>> T normalize(T a) {
return a.negate().negate();
}
You would implement this interface like so
public static class MyBoolean implements Negatable<MyBoolean> {
public boolean a;
public MyBoolean(boolean a) {
this.a = a;
}
#Override
public MyBoolean negate() {
return new MyBoolean(!this.a);
}
}
In fact, the Java standard library uses this exact trick to implement Comparable.
public interface Comparable<T> {
int compareTo(T o);
}
In general, no.
You can use tricks (as suggested in the other answers) that will make this work, but they do not provide all of the same guarantees that the Haskell typeclass does. Specifically, in Haskell, I could define a function like this:
doublyNegate :: Negatable t => t -> t
doublyNegate v = negate (negate v)
It is now known that the argument and return value of doublyNegate are both t. But the Java equivalent:
public <T extends Negatable<T>> T doublyNegate (Negatable<T> v)
{
return v.negate().negate();
}
doesn't, because Negatable<T> could be implemented by another type:
public class X implements Negatable<SomeNegatableClass> {
public SomeNegatableClass negate () { return new SomeNegatableClass(); }
public static void main (String[] args) {
new X().negate().negate(); // results in a SomeNegatableClass, not an X
}
This isn't particularly serious for this application, but does cause trouble for other Haskell typeclasses, e.g. Equatable. There is no way of implementing a Java Equatable typeclass without using an additional object and sending an instance of that object around wherever we send values that need comparing, (e.g:
public interface Equatable<T> {
boolean equal (T a, T b);
}
public class MyClass
{
String str;
public static class MyClassEquatable implements Equatable<MyClass>
{
public boolean equal (MyClass a, MyClass b) {
return a.str.equals(b.str);
}
}
}
...
public <T> methodThatNeedsToEquateThings (T a, T b, Equatable<T> eq)
{
if (eq.equal (a, b)) { System.out.println ("they're equal!"); }
}
(In fact, this is exactly how Haskell implements type classes, but it hides the parameter passing from you so you don't need to figure out which implementation to send where)
Trying to do this with just plain Java interfaces leads to some counterintuitive results:
public interface Equatable<T extends Equatable<T>>
{
boolean equalTo (T other);
}
public MyClass implements Equatable<MyClass>
{
String str;
public boolean equalTo (MyClass other)
{
return str.equals(other.str);
}
}
public Another implements Equatable<MyClass>
{
public boolean equalTo (MyClass other)
{
return true;
}
}
....
MyClass a = ....;
Another b = ....;
if (b.equalTo(a))
assertTrue (a.equalTo(b));
....
You'd expect, due to the fact that equalTo really ought to be defined symmetrically, that if the if statement there compiles, the assertion would also compile, but it doesn't, because MyClass isn't equatable with Another even though the other way around is true. But with a Haskell Equatable type class, we know that if areEqual a b works, then areEqual b a is also valid. [1]
Another limitation of interfaces versus type classes is that a type class can provide a means of creating a value which implements the type class without having an existing value (e.g. the return operator for Monad), whereas for an interface you must already have an object of the type in order to be able to invoke its methods.
You ask whether there is a name for this limitation, but I'm not aware of one. It's simply because type classes are actually different to object-oriented interfaces, despite their similarities, because they are implemented in this fundamentally different way: an object is a subtype of its interface, thus carries around a copy of the interface's methods directly without modifying their definition, while a type class is a separate list of functions each of which is customised by substituting type variables. There is no subtype relationship between a type and a type class that has an instance for the type (a Haskell Integer isn't a subtype of Comparable, for example: there simply exists a Comparable instance that can be passed around whenever a function needs to be able to compare its parameters and those parameters happen to be Integers).
[1]: The Haskell == operator is actually implemented using a type class, Eq ... I haven't used this because operator overloading in Haskell can be confusing to people not familiar with reading Haskell code.
I interpret the question as
How can we implement ad-hoc polymorphism using typeclasses in Java?
You can do something very similar in Java, but without the type safety guarantees of Haskell - the solution presented below can throw errors at runtime.
Here is how you can do it:
Define interface that represents the typeclass
interface Negatable<T> {
T negate(T t);
}
Implement some mechanism that allows you to register instances of the typeclass for various types. Here, a static HashMap will do:
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
Define the normalize method that uses the above mechanism to get the appropriate instance based on the runtime class of the passed object:
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
Register actual instances for various classes:
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
Use it!
System.out.println(normalize(false)); // Boolean `false`
System.out.println(normalize(42)); // Integer `42`
The main drawback is that, as already mentioned, the typeclass instance lookup can fail at runtime, not at compile-time (as in Haskell). Using a static hash map is suboptimal too, because it brings all the problems of a shared global variable, this could be mitigated with more sophisticated dependency injection mechanisms. Automatically generating typeclass instances from other typeclass instances, would require even more infrastructure (could be done in a library). But in principle, it implements ad-hoc polymorphism using typeclasses in Java.
Full code:
import java.util.HashMap;
class TypeclassInJava {
static interface Negatable<T> {
T negate(T t);
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
}
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
static {
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
}
public static void main(String[] args) {
System.out.println(normalize(false));
System.out.println(normalize(42));
}
}
You're looking for generics, plus self typing. Self typing is the notion of generic placeholder that equates to the class of the instance.
However, self typing doesn't exist in java.
You can get close with generics, but it's clunky:
public interface Negatable<T> {
public T negate();
}
Then
public class MyBoolean implements Negatable<MyBoolean>{
#Override
public MyBoolean negate() {
//your impl
}
}
Some implications for implementers:
They must specify themselves when they implement the interface, e.g. MyBoolean implements Negatable<MyBoolean>
Extending MyBoolean would require one to override the negate method again.

create new Bounded Type Parameter

I'm looking to implement a generic search function to basically look if a mouse click is within one of several list of rectangles (of varying types, all children of G3_gRect). When nothing is found, it should return a new object of type T with a property defining it as being invalid (as opposed to other things that it could be).
This all works fine until I try to make it return the generic type T.
What can I do differently to make this work?
This breaks in the last line when trying to initialize a new object of type T. I assume because it doesn't know that it could always initialize that type.
private <T extends G3_gRect> T whatRect(MouseEvent e, List<List<T>> maps) {
while (!maps.isEmpty()) {
List<T> map = maps.remove(0);
for (T entry : map) {
if(entry.R.contains(e.getPoint())) return entry;
}
}
return new T(G2_gObj.ObjType.NONE); //return with empty object rather than null.
}
A few of the relevant parts of related classes:
public abstract class G2_gObj {
public enum ObjType {
FUNCTION, RIBBON, D_LINE, D_START, D_END, D_IN_AREA, C_IN_AREA, M_IN_AREA, D_OUT_AREA, M_OUT_AREA, NONE, C_OUT_AREA
}
public ObjType t;
public G2_gObj(ObjType t) {
this.t = t;
}
}
public class G3_gRect extends G2_gObj{
public G3_gRect(ObjType t) {
super(t);
}
}
public class G4_gFunct extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
public class G4_gDPoint extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
Right now my workaround is to pass in an object of type T into this method to return if nothing is found. It works, its fine, but I imagine there is a better way to actually make this work.
Thanks!
There's no way to construct an object without knowing its exact class. Barring the use of reflection, your only option would be to have the caller pass a default value, or to return null (which would avoid unnecessary object creation).
If you do want to use reflection (a questionable decision), you can have a parameter Class<T> clazz, and return
clazz.getConstructor(ObjType.class).newInstance(G2_gObj.ObjType.NONE)

Function with generic list parameter? (Overloading function)

Objective: What I need is to create a function or functions to handle different types of List parameter, and I will be iterating through the list in the function.
Attempts:
1- Multiple functions with different type of List
public static int update(List<MyClass> myClasses){};
public static int update(List<Project> rojects){};
public static int update(List<Time> times){};
But that deemed to be in-compilable as due to multiple functions with same parameter type List.
2- Generic type of list, and using (instanceof) However, I failed to completely do this as I am not sure how, and as much as I read, this seems to be an unfavorable way of such action.
My question: what is the Java way of implementing such requirement? I need a clean code, I don't care if it is complicated, I care mostly about accuracy and proper coding.
PS: if the instanceof the correct way, then would you please provide me with a small example on how to iterate the list with the different types.
Thanks in advance :)
EDIT: The different objects have no relation with each other, as in, they do not extend each other nor do they extend a super class. The blocks of each function are generating an SQLite statements which would be different for each type.
Respond to 'harsh's answer:
So I ended up using a combination of your suggestions, and that is to implement a base class with a function of getClassType() which returns a string of the class name, then I would check the returned value in the update(List<T> list) function.
public static <T extends Item> int update(List<T> list){
...
// Loop through the list and call the update function
for (T item: list){
if (item.getClassType() == MyClass.CLASS_TYPE)
update((MyClass) item);
}
...
}
public interface Item {
/**
* #return Return the class type, which is the name of the class
*/
public String getClassType();
}
public class ClassProject implements Item{
public static final String CLASS_TYPE = "ClassProject";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class ClassTime implements Item{
public static final String CLASS_TYPE = "ClassTime";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class MyClass implements Item{
public static final String CLASS_TYPE = "MyClass";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
Reason for doing this whole interface is because I don't like istanceof and not sure about it's performance and cost, so I attempted to make one of my own. Now is this a terrible way of doing this?
Can you do something like this:
public class Update<T>
{
public static int update(List<T> objects){};
}
OR
public static <T> int update(List<T> objects){};
whichever is more appropriate in your case.
So if you go by second approach and due to type erasure at runtime, you are left with instanceof checking:
public static <T> int update(List<T> objects){
for(T object : objects)
{
if(object.getClass().isInstance(Pair.class))
{
//do something
}else if(object.getClass().isInstance(Time.class))
{
}
}
return 0;
}
But that's doesn't look a good design, you can improve above by using a factory method:
static Handler getHandler(Class<?> handlerClass)
{
if(handlerClass.isInstance(Project.class))
{
//return ProjectHandler
}else if(handlerClass.isInstance(Time.class))
{
//return TimeHandler
}
//return errorHandler
}
interface Handler {
int handle();
}
public static <T> int update(List<T> objects){
for(T object : objects)
{
getHandler(object.getClass()).handle();
}
return 0;
}
Now a nicer approach IMO would be to designate your classes under update via marker interface and then cleanly handle update in each of the classes:
interface Updateable {
int update();
}
public static <T extends Updateable> int update2(List<T> objects){
for(T object : objects)
{
object.update();
}
return 0;
}
Based on your answer to my comment you are left with two approaches. The first would be to try to come up with an interface that all the possible types that would be passed to this method implement. If your interface was called Foo you could define the method as something like:
public int update(List<Foo> list)
Then your code inside would be based on the methods available in Foo.
If you can't do this then you will need separate methods per possible type. You can't do instanceof at runtime due to Type Erasure. The underlying type if the list is erased in the compiled code and therefor will not be available for instanceof logic.
EDIT:
To clear up a little confusion on my above answer. You can do instanceof on a per element basis when iterating the list, something like this:
for(Object item:list){
if (item instanceof A){
//do A based logic
}
else if (item instanceof B){
//do B based logic
}
}
You can't however check the list type at runtime like so:
if (list instanceof List<A>)
Your best bet really would be to try and generalize the types supported via an interface as suggested in my first solution. Doing the instanceof approach will lead to code that will constantly need to be modified as you add more supported types.
Expanding harsh's answer, can't you do:
public class Update
{
public static <T> int update(List<T> objects, Class<T> clazz){};
}
And then, in your implementation, vary behavior according to the passed Class instance?

Using Java Generics to recurse over an object with a list of objects (each with another list of objects)

I have three interfaces:
public interface Combinable<V> {
V add(V other);
}
public interface Sublistable<V> {
boolean hasSublist();
List<V> getSublist();
void setSublist(List<V> sublist);
}
public interface HasUniqueIdentifier {
String getUniqueIdentifier();
}
and 4 classes that implement some or all of these interfaces:
public class Grandparent implements HasUniqueIdentifier,
Sublistable<Parent>,
Combinable<Grandparent>
{ List<Parent> sublist; ... }
public class Parent implements HasUniqueIdentifier,
Sublistable<Child>,
Combinable<Parent>
{ List<Child> sublist; ... }
public class Child implements HasUniqueIdentifier,
Sublistable<Grandchild>,
Combinable<Child>
{ List<Grandchild> sublist; ... }
public class Grandchild implements HasUniqueIdentifier,
Combinable<Grandchild>
{ }
I would like to have a generic method that does the following:
public <V, T extends HasUniqueIdentifier & Combinable<T> & Sublistable<V>>
List<T> combine(List<T> items) {
Multimap<String, T> similarItemMap = HashMultimap.create();
for (T item: items) {
similarItemMap.put(item.getUniqueIdentifier(), item);
}
List<T> output = new ArrayList<T>();
for (Collection<T> similarCollection : similarItemMap.asMap().values()) {
List<T> similarItems = Lists.newArrayList(similarCollection);
T source = similarItems.get(0);
for (int i = 0; i < similarItems.size(); i++) {
source = source.add(similarItems.get(i));
}
output.add(source);
}
for (T item : output) {
if (item.hasSublist()) {
item.setSublist(combine(item.getSublist));
}
}
return output;
}
Realizing that this could create an infinite loop (unless the bottom class -- Grandchild -- implemented Sublistable and set hasSublist() { return false; }, or something), as well as the fact that this method is kind of crazy with generics, I have to ask: Is there some way that I can rewrite this a bit so that I can call the method in this way:
combine(listOfGrandparents)
or should I give up on this being one method and try to refactor it in a better way?
Edit:
To better explain what it is that I'm trying to do, I have a list of objects of type A. Each object a has a list of objects of type B. Each object b has a list of objects of type C, and so on, until eventually type T (for some varying level of T) doesn't have a sublist anymore.
Each type basically has three things that it needs to do for a "merge" or "combine" method:
Collect all "like" items into a container, using the item.getUniqueIdentifier() method
Combine all the like items into one item, using the source.add(other) method
If the item has a sublist, do a merge on the sublist.
Since each item behaves so similarly, it would be nice if I could use a single method instead of having to have n methods, one for each type. Unfortunately, since none of the types are guaranteed to be the same (other than having implemented some or all of the given interfaces above), creating a generic method proves to be difficult. Is there some way to do this that I'm missing?
Edit 2:
I've found a method that kind of works. Basically, it changes to this:
public <V extends HasUniqueIdentifier & Combinable<V>,
T extends HasUniqueIdentifier & Combinable<T>>
List<T> combine(List<T> items) {
Multimap<String, T> similarItemMap = HashMultimap.create();
for (T item: items) {
similarItemMap.put(item.getUniqueIdentifier(), item);
}
List<T> output = new ArrayList<T>();
for (Collection<T> similarCollection : similarItemMap.asMap().values()) {
List<T> similarItems = Lists.newArrayList(similarCollection);
T source = similarItems.get(0);
for (int i = 0; i < similarItems.size(); i++) {
source = source.add(similarItems.get(i));
}
output.add(source);
}
for (T item : output) {
if (item instanceof Sublistable<?>) {
#SuppressWarnings("unchecked")
Sublistable<V> sublistableItem = ((Sublistable<V>)sublistableItem);
if (sublistableItem.hasSublist()) {
sublistableItem.setSublist(combine(sublistableItem.getSublist));
}
}
}
return output;
}
Unfortunatey, this method requires both a #SupressWarnings and an instanceof, which I would like to avoid if possible. I haven't found anything else, though, yet.
Your first solution is fine, given that GrandChild implements Sublistable<Void> vacuously. The tree is more uniform and easier to handle recursively. You may also want to have one merged interface Node<T,V> extends HasUniqueIdentifier, Combinable<T>, Sublistable<V>{}
If you don't want GrandChild implements Sublistable, your 2nd solution is also fine. A single instanceof to test a marker interface isn't a sin. The code can be rewritten as
public <T extends HasUniqueIdentifier & Combinable<T>>
List<T> combine(List<T> items)
{
...
List<T> output = new ArrayList<T>();
...
for (T item : output) {
if (item instanceof Sublistable<?>)
combineSublist((Sublistable<?>)item);
return output;
}
private <V> void combineSublist(Sublistable<V> sublistableItem)
{
if (sublistableItem.hasSublist()) {
sublistableItem.setSublist(combine(sublistableItem.getSublist));
}

Java generics: capture cannot be applied to Object

I have code that has a Map of (Message)Handlers. I'm trying to make the handlers generified (as seen by the interface Handler). Without generics the handlers all need to cast from Object to the respective class, which would be nice to avoid (but everything works). For each message class (Foo below) I have a handler class.
How can I keep a Map of any kind of Class to any kind of Handlers and get/call with "just" an Object? (the parameter to handleMessage(Object) can't be restricted)
See MWE below.
import java.util.*;
public class Logic
{
Map<Class<?>, Handler<?>> handlers = new HashMap<Class<?>, Handler<?>>();
public void run()
{
handlers.put(Foo.class, new FooHandler());
}
public void handleMessage(Object msg)
{
Handler<?> handler = handlers.get(msg.getClass());
if (handler != null) {
handler.execute(msg);
}
}
private interface Handler<T>
{
public void execute(T msg);
}
private class FooHandler implements Handler<Foo>
{
public void execute(Foo msg) {}
}
private class Foo {}
}
This code produces:
Logic.java:16: execute(capture#x of ?) in Logic.Handler cannot be applied > to (java.lang.Object)
handler.execute(msg);
How can this be repaired to work while still keeping the Handler interface generic?
You can't define the relationship between the key and the value in a field, but you can use accessor methods to enforce it, provided only these methods are used to access the map.
private final Map<Class, Handler> handlers = new HashMap<Class, Handler>();
public <T> void addHandler(Class<T> clazz, Handler<T> handler) {
handlers.put(clazz, handler);
}
#SuppressWarnings("unchecked")
public <T> Handler<T> getHandler(Class<T> clazz) {
return (Handler<T>) handlers.get(clazz);
}
#SuppressWarnings("unchecked")
public <T> Handler<T> getHandlerFor(T t) {
return getHandler((Class<T>) t.getClass());
}
public void run() {
addHandler(Foo.class, new FooHandler());
}
public <T> void handleMessage(T msg) {
Handler<T> handler = getHandlerFor(msg);
if (handler != null) {
handler.execute(msg);
}
}
The problem is that execute() takes a certain parameter type, that is more specific than Object.
However, in your handleMessage() method, the compiler doesn't know what type the parameter is. Suppose a case where FooHandler is registered for class Bar (which would be possible).
In that context handler.execute(msg); would actually result in FooHandler#execute(Foo) being called with a Bar argument, which would result in a ClassCastException (unless Bar extends Foo). Thus the compiler refuses to compile that code.
Another answer that wasn't here but it should be - remove all of the generics syntax (i.e. remove all the <?>). Then the parser will revert to JDK1.4 syntax and this will all work fine.

Categories

Resources