148

在 Java 代码段中:

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

最后一行生成警告

“类型的表达List需要未经检查的转换才能符合List<SyndEntry>

解决此问题的适当方法是什么?

4

10 回答 10

124

这是处理 Java 5 之前的 API 时的常见问题。要自动化来自 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.

于 2010-05-17T10:29:43.993 回答
102

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

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

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

于 2008-12-15T07:23:23.803 回答
27

看起来SyndFeed没有使用泛型。

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

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

或致电Collections.checkedList - 尽管您仍然需要禁止显示警告:

@SuppressWarnings("unchecked")
List<SyndEntry> entries = Collections.checkedList(sf.getEntries(), SyndEntry.class);
于 2008-12-15T07:05:20.843 回答
9

你写了SyndFeed吗?

是否sf.getEntries返回 List 或List<SyndEntry>? 我的猜测是它返回List并将其更改为返回List<SyndEntry>将解决问题。

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

于 2008-12-15T06:55:20.753 回答
2

如果您正在使用 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));
于 2014-12-18T02:11:53.303 回答
1

如果您查看该类的 javadoc SyndFeed(我猜您指的是该类com.sun.syndication.feed.synd.SyndFeed),则 getEntries() 方法不会返回java.util.List<SyndEntry>,而是仅返回java.util.List.

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

于 2008-12-15T06:55:55.310 回答
1
SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<?> entries = sf.getEntries();
于 2015-05-08T07:30:22.383 回答
0

如果您不想在每个 sf.getEntries() 调用上放置 @SuppressWarning("unchecked"),您始终可以创建一个将返回 List 的包装器。

看到这个另一个问题

于 2008-12-16T04:08:56.207 回答
0

更容易

return new ArrayList<?>(getResultOfHibernateCallback(...))

于 2011-05-16T15:07:32.407 回答
0

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;
}
于 2021-11-25T19:29:59.073 回答