【问题标题】:Fixing unchecked call to raw type warning Java修复未经检查的对原始类型警告 Java 的调用
【发布时间】:2017-07-12 23:57:31
【问题描述】:

我的代码如下所示。我在摄取方法中使用 Handler 原始类型时遇到了一些未经检查的警告。我被困在删除警告和我使用原始类型的最佳方法上。我的主要绊脚石是摄取方法参数是 IV2GraphObject 并且任何尝试在处理程序上设置边界都会在尝试调用处理程序上的句柄方法时产生编译错误。

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

【问题讨论】:

  • 为什么有getInstance 而不是构造函数?似乎不是单例。为什么要通过(而不是使用)VisalloEnv environmentgraphFactory 是什么?您添加到handlers 的所有这些类是什么?你得到的实际错误是什么?
  • 我认为没有任何方法可以完全避免使用给定结构的警告。这只是你想要哪个警告以及在哪里的问题。
  • 为什么@SuppressWarnings("rawtypes") 不起作用?虽然我什至看不到这段代码是如何编译的
  • 您的ingest 方法可以接受IV2GraphObject 的任何子类型。然后您尝试将其传递给处理程序,该处理程序只接受IV2GraphObject 的某个子类型。应该重新考虑你的设计,这没有意义。
  • 我想我已经回答了我自己的问题。我不想改变摄取方法的行为。我希望它按照我定义的方式工作以采用任何类型的 IV2GraphObject,因为这实际上只是我控制的内部结构。我只需要在 Handler 接口中调整我的句柄方法定义。我将其定义如下,并且能够删除我添加的 SuppressWarning 注释。我敢肯定,它可能会更好,但它满足我的直接需求。 void handle(T iv2Object);

标签: java generics


【解决方案1】:

首先,您有一个从类到处理程序的映射,您希望将每个Class&lt;T&gt; 映射到Handler&lt;T&gt;,但是您不能用映射的类型表达这种关系。为了安全地执行此操作,您应该创建一个新类,其 API 强制参数类型和 getput 的返回值之间的关系(该类内部仍有未经检查的强制转换,但该类的 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&lt;? extends IV2GraphObject&gt;,与ingestable(即IV2GraphObject)的类型连接过于松散。你理想中想要的是ingestableClassClass&lt;T&gt;ingestableT 对于一些T。这样handlers.get(ingestableClass) 将返回Handler&lt;T&gt;handler.handle(ingestable) 将编译。

.getClass()的返回类型中有? extends的原因是ingestable的实际运行时类可能是IV2GraphObject的子类型(其实这里应该一直是子类型),因此它的类不是Class&lt;IV2GraphObject&gt;。但是,我们知道存在一个类型T(对象的实际运行时类型),其中ingestableT的一个实例,ingestable.getClass()Class&lt;T&gt;的一个实例;但是,我们如何获得T?我们可以使用辅助方法和捕获从通配符? 中获取T

helper(ingestableClass, ...);

private <T extends IV2GraphObject> void helper(Class<T> clazz, ...) { ... }

但是,即使我们这样做,编译器仍然不知道ingestable 是同一类型T 的实例(我们知道它一定是,但编译器只知道ingestable 是一个实例IV2GraphObject)。我们可以使用类的.cast() 将其转换为T 类型而不会发出任何警告(我们知道转换总是会成功,但我们这样做只是为了编译而没有警告;我们也可以直接执行(T) cast 会产生警告):

public void ingest(IV2GraphObject ingestable) {
    Class<? extends IV2GraphObject> ingestableClass = ingestable.getClass();
    helper(ingestableClass, ingestable);
}

private <T extends IV2GraphObject> void helper(Class<T> clazz, IV2GraphObject ingestableTemp) {
    T ingestable = clazz.cast(ingestableTemp);
    Handler<T> handler = handlers.get(ingestableClass);
    try {
        handler.handle(ingestable);
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多