【问题标题】:How do I fix "The expression of type List needs unchecked conversion...'?如何解决“List 类型的表达式需要未经检查的转换...”?
【发布时间】:2010-09-26 22:15:00
【问题描述】:

在 Java sn-p 中:

SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<SyndEntry> entries = sf.getEntries();

最后一行产生警告

"List 类型的表达式需要未经检查的转换才能符合List&lt;SyndEntry&gt;"

有什么合适的方法来解决这个问题?

【问题讨论】:

    标签: java warnings unchecked-conversion


    【解决方案1】:

    这是处理 Java 5 之前的 API 时的常见问题。要自动化solution from erickson,您可以创建以下通用方法:

    public static <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
        List<T> r = new ArrayList<T>(c.size());
        for(Object o: c)
          r.add(clazz.cast(o));
        return r;
    }
    

    这允许你做:

    List<SyndEntry> entries = castList(SyndEntry.class, sf.getEntries());
    

    因为此解决方案通过强制转换检查元素确实具有正确的元素类型,所以它是安全的,并且不需要SuppressWarnings

    【讨论】:

    • 关于 Bruno 建议的方法,如果 List 包含许多元素,这会不会损害应用程序的性能? Java 必须对它们中的每一个进行强制转换。
    • 如果你想要保证,那就是成本。还有其他更便宜的选择吗?显然,如果您可以控制调用的原始集合返回方法,甚至可以调用该方法或使用惰性需求方法访问集合。在方法调用之后考虑整个集合的任何内容?
    【解决方案2】:

    由于getEntries 返回一个原始的List,它可以容纳任何东西。

    无警告的方法是创建一个新的List&lt;SyndEntry&gt;,然后将sf.getEntries() 结果的每个元素转换为SyndEntry,然后再将其添加到新列表中。 Collections.checkedList 不会 为您执行此检查 - 尽管可以实现它来执行此操作。

    通过预先进行自己的转换,您“遵守了 Java 泛型的保证条款”:如果引发了 ClassCastException,它将与源代码中的转换相关联,而不是插入的不可见转换由编译器。

    【讨论】:

    • 谢谢——这是一个有趣的见解,关于“保修”和编译器完成的隐形转换与我自己的代码中明确完成的转换。
    • 是的,未具体化的泛型的价值是有限的,但这是它确实提供的一件事。澄清一下,这要求您的代码在没有类型安全警告的情况下编译。
    • 嗨,埃里克森,我同意这确实是最好的解决方案。查看我的回答 stackoverflow.com/questions/367626/… 以获得此解决方案的通用版本。
    【解决方案3】:

    看起来SyndFeed 没有使用泛型。

    你可以有一个不安全的演员和一个警告抑制:

    @SuppressWarnings("unchecked")
    List<SyndEntry> entries = (List<SyndEntry>) sf.getEntries();
    

    或致电Collections.checkedList - 尽管您仍然需要取消警告:

    @SuppressWarnings("unchecked")
    List<SyndEntry> entries = Collections.checkedList(sf.getEntries(), SyndEntry.class);
    

    【讨论】:

    • 既然他们都抑制了警告,那么对其中一个或另一个有什么好处,或者偏好?谢谢!另外:如果存在未经检查的抑制,是否需要强制转换?
    • @Yar:好吧,Collections.checkedList 将阻止以后添加任何非 SyndEntry 元素。我个人很少使用checkedList,但无论如何我也不会经常陷入这种未经检查的演员阵容......
    【解决方案4】:

    SyndFeed 是你写的吗?

    sf.getEntries 是返回 List 还是 List&lt;SyndEntry&gt;?我的猜测是它返回 List 并将其更改为返回 List&lt;SyndEntry&gt; 将解决问题。

    如果SyndFeed 是库的一部分,我认为您可以在不向方法中添加@SuppressWarning("unchecked") 注释的情况下删除警告。

    【讨论】:

    【解决方案5】:

    如果您正在使用 Guava,并且您只想遍历您的值:

    for(SyndEntry entry: Iterables.filter(sf.getEntries(), SyndEntry.class){
      ...
    }
    

    如果你需要一个实际的列表,你可以使用

    List<SyndEntry> list = Lists.newArrayList(
        Iterables.filter(sf.getEntries(), SyndEntry.class));
    

    List<SyndEntry> list = ImmutableList.copyOf(
        Iterables.filter(sf.getEntries(), SyndEntry.class));
    

    【讨论】:

      【解决方案6】:
      SyndFeedInput fr = new SyndFeedInput();
      SyndFeed sf = fr.build(new XmlReader(myInputStream));
      List<?> entries = sf.getEntries();
      

      【讨论】:

      • 即使这里提供的代码解决了问题,我还是建议您简要解释一下为什么会这样。请解释为什么发布的答案可以解决问题。
      【解决方案7】:

      如果您查看 SyndFeed 类的 javadoc(我猜您指的是 com.sun.syndication.feed.synd.SyndFeed 类),getEntries() 方法不会返回 java.util.List&lt;SyndEntry&gt;,而只返回 java.util.List

      所以你需要一个明确的演员表。

      【讨论】:

        【解决方案8】:

        如果您不想在每个 sf.getEntries() 调用中添加 @SuppressWarning("unchecked"),您可以随时创建一个返回 List 的包装器。

        this other question

        【讨论】:

          【解决方案9】:

          更简单

          return new ArrayList&lt;?&gt;(getResultOfHibernateCallback(...))

          【讨论】:

          • 那么您将在使用时为 ArrayList> 中的每个元素处理正确的转换(重新转换?)。
          【解决方案10】:

          Bruno De Fraine 的回答很棒。但是,如果输入参数“Collection> c”的大小为 0,则例程会因空指针而崩溃。 我建议做一个小的改进来避免这种情况(我给出了 HashSet 的版本):

          public static <T> HashSet<T> castHashSet(Class<? extends T> clazz, Collection<?> c) {
            int cSize = (c == null) ? 0 : c.size();
            HashSet<T> hashSet = new HashSet<T>(cSize);
            if (c != null) {
              for (Object o : c)
                hashSet.add(clazz.cast(o));
              }
              return hashSet;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-15
            • 1970-01-01
            • 2022-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多