我有一个处理程序的通用接口:
public interface EventHandler<T> {
boolean handleEvent(T message);
}
您可以实施此界面并处理T message
。您必须将实现的实例传递给EventDispatcher
实例。该类在内部存储多个不同类型的EventHandler
个实例。
在某个时刻触发事件,EventDispatcher
实例调用相应的EventHandler
的{{1}}方法,并传递与handleEvent()
类型相同的消息。问题是我不知道哪个是确切的类型,但我确信我传递给EventHandler
实例的T message
具有相同的“T”。
我打电话的方式使用原始类型和作品:
EventHandler
,但我收到警告“未经检查调用'handleEvent(T)'作为原始类型'EventHandler'”的成员。
是否可以使用泛型来避免警告?
我想到的一个可能的解决方案是创建一个通用的包装器方法:
EventHandler handler = getHandler();
Object message = getMessage();
handler.handleEvent(message);
并使用它:
private <T> boolean handleEventGeneric(EventHandler<T> handler, T message) {
return handler.handleEvent(message);
}
但我不喜欢我必须制作包装方法的事实。有更优雅的解决方案吗?
答案 0 :(得分:1)
无法删除此警告(或至少没有@SuppressWarning
)。摆脱它的唯一方法是做两件事:
@SuppressWarning("unchecked")
。警告就在那里,以便您可以在代码中轻松识别出类型安全方面的弱点。如果您正确使用注释,那么您的代码是安全的,并且您确定没有得到任何令人不快的ClassCastException
,除非您愿意在一个您实际上不确定的地方添加@SuppressWarning("unchecked")
这种类型是安全的。
请参阅说明我的观点的一些演示代码:
import java.util.HashMap;
import java.util.Map;
public class TestGenerics {
private Map<Class<?>, EventHandler<?>> handlers = new HashMap<Class<?>, TestGenerics.EventHandler<?>>();
public interface EventHandler<T> {
boolean handleEvent(T message);
}
// Here you force the invoker to provide the correct type of event handler
// with the given type of klass
// If he wants to make this fail, then he will have to use rawtype
public <T> void registerHandler(Class<T> klass, EventHandler<T> handler) {
handlers.put(klass, handler);
}
public <T> void handle(T message) {
@SuppressWarnings("unchecked") // Here you can add this annotation since you are forcing any invoker to provide a correct EventHandler
EventHandler<T> handler = (EventHandler<T>) handlers.get(message.getClass());
if (handler != null) {
handler.handleEvent(message);
}
}
public static void main(String[] args) {
TestGenerics test = new TestGenerics();
test.registerHandler(Long.class, new EventHandler<Long>() {
@Override
public boolean handleEvent(Long message) {
System.out.println("Received a long " + message);
return true;
}
});
// Here I use raw type but this also means that I created a weak spot in
// terms of type safety
EventHandler handler2 = new EventHandler<String>() {
@Override
public boolean handleEvent(String message) {
System.out.println("THis will never print " + message);
return false;
}
};
test.registerHandler(Integer.class, handler2); // This is where the
// problem comes from
test.handle(3L); // OK
test.handle(1); // ClassCastException
}
}
答案 1 :(得分:-1)
你可以这样做:
EventHandler<Object> handler = getHandler();
Object message = getMessage();
handler.handleEvent(message);
这不安全,但不比现在安全。