我有如下所示的代码。我在ingest方法中使用Handler raw类型时遇到了几个未经检查的警告。我坚持使用删除警告和我对原始类型的使用的最佳方法。我的主要障碍是ingest方法参数是IV2GraphObject,并且在尝试在处理程序上调用handle方法时,任何在Handler上设置边界的尝试都会产生编译错误。
public class IV2Ingestor implements Ingestor<IV2GraphObject> {
public interface Handler<T extends IV2GraphObject> {
void handle(T iv2Object);
Set<? extends Element> getNewElements();
}
// map of handlers for supported objects
private Map<Class<? extends IV2GraphObject>, Handler<? extends IV2GraphObject>> handlers;
public static IV2Ingestor getInstance(VisalloEnv environment) {
// create a new instance
IV2Ingestor ingestor = new IV2Ingestor();
ingestor.handlers = new HashMap<>();
ingestor.handlers.put(Tweet.class, new TweetHandler(graphFactory));
ingestor.handlers.put(TwitterUser.class, new TwitterUserHandler(graphFactory));
ingestor.handlers.put(GoogleNews.class, new GoogleNewsHandler(graphFactory));
ingestor.handlers.put(VKPost.class, new VKPostHandler(graphFactory));
ingestor.handlers.put(YouTube.class, new YouTubeHandler(graphFactory));
ingestor.handlers.put(Instagram.class, new InstagramHandler(graphFactory));
// return ingestor
return ingestor;
}
@Override
public void ingest(IV2GraphObject ingestable) {
Class<? extends IV2GraphObject> ingestableClass = ingestable.getClass();
if (handlers.containsKey(ingestableClass)) {
Handler handler = handlers.get(ingestableClass);
try {
handler.handle(ingestable);
} finally {
// persist changes
graph.flush();
// notify GPWs of any new graph elements
workQueueRepository.pushElements(handler.getNewElements(), Priority.LOW);
}
}
}
答案 0 :(得分:0)
首先,您有一个从类到处理程序的映射,您希望每个Class<T>
映射到Handler<T>
,但您无法用Map的类型表达该关系。要安全地执行此操作,您应该创建一个新类,其API强制执行参数类型中的关系并返回get
和put
的值(该类内部仍然具有未经检查的强制转换,但是类的API保证这是安全的):
class ClassToHandler {
private Map<Class<? extends IV2GraphObject>, Handler<? extends IV2GraphObject>> map
= HashMap<>();
@SuppressWarnings("unchecked")
public <T extends IV2GraphObject> Handler<T> get(Class<T> clazz) {
return (Handler<T>)map.get(clazz);
}
public <T extends IV2GraphObject> void put(Class<T> clazz, Handler<T> handler) {
map.put(clazz, handler);
}
}
你会handlers
成为这个类的对象。这样,您就可以拨打handlers.get()
来返回更好的类型。
第二个问题是ingestable.getClass()
返回类型Class<? extends IV2GraphObject>
,它与ingestable
(IV2GraphObject
的类型过于松散地联系在一起。对于某些ingestableClass
,您理想的是Class<T>
为ingestable
而T
为T
。这样handlers.get(ingestableClass)
将返回Handler<T>
,handler.handle(ingestable)
将会编译。
返回类型? extends
中.getClass()
的原因是ingestable
的实际运行时类可能是IV2GraphObject
的子类型(事实上,在这里,它应该始终是一个子类型),因此它的类不是Class<IV2GraphObject>
。但是,我们知道存在类型T
(对象的实际运行时类型),其中ingestable
是T
的实例,ingestable.getClass()
是{的实例{1}};但是,我们如何得到Class<T>
?我们可以使用辅助方法和捕获来从通配符T
中获取T
:
?
但是,即使我们这样做,编译器仍然不知道helper(ingestableClass, ...);
private <T extends IV2GraphObject> void helper(Class<T> clazz, ...) { ... }
是同一类型ingestable
的实例(我们知道它必须是,但编译器只知道T
1}}是ingestable
)的一个实例。我们可以使用类的IV2GraphObject
将其强制转换为.cast()
类型,而不会发出任何警告(我们知道强制转换将始终成功,但我们只是为了编译而没有警告;我们也可以直接完成一个T
演员会产生警告):
(T)