2008-12-15 6 views
115

В Java фрагмент кода:Как исправить «Выражение списка типов необходимо беспрепятственное преобразование ...

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

последняя строка выдает предупреждение

«Выражение из типа List потребностей бесконтрольно преобразования, чтобы соответствовать List<SyndEntry> "

Что подходящий способ исправить это?

ответ

81

С getEntries возвращает сырым List, он мог держать что угодно.

Беспроблемный подход заключается в создании нового List<SyndEntry>, а затем отбрасывает каждый элемент sf.getEntries() до SyndEntry, прежде чем добавлять его в новый список. Collections.checkedList делает не сделайте это для вас —, хотя было бы возможно реализовать его для этого.

Выполняя свою личную настройку, вы «соблюдаете условия гарантии» генерических файлов Java: если поднят ClassCastException, он будет связан с литой в исходном коде, а не с невидимым литьем, вставленным компилятор.

+9

Спасибо - это интересное представление о« гарантии »и невидимой передаче, сделанной компилятором по сравнению с литой, сделанной явно в моем собственном коде. – user46277 2008-12-16 05:30:03

7

ли вы написать SyndFeed?

sf.getEntries возвращение списка или List<SyndEntry>? Я предполагаю, что он вернет List и сменив его на возврат List<SyndEntry> устранит проблему.

Если SyndFeed является частью библиотеки, я не думаю, что вы можете удалить предупреждение без добавления аннотации @SuppressWarning("unchecked") к вашему методу.

+0

Вы также можете добавить явное выражение. – Uri 2008-12-15 06:58:47

+2

Листинг просто произведет еще одно предупреждение, так как код не является безопасным. – erickson 2008-12-15 07:15:12

+0

`SyndFeed` происходит от https://rometools.github.io/rome/ROMEReleases/ROME1.0Release.html. Проблема, похоже, исправлена ​​в более поздних версиях Рима, как и в https://mvnrepository.com/artifact/com.rometools/rome/1.9.0 – daloonik 2017-12-06 14:28:42

1

Если вы посмотрите на Javadoc для класса SyndFeed (я думаю, вы имеете в виду класс com.sun.syndication.feed.synd.SyndFeed), метод getEntries() не возвращает java.util.List<SyndEntry>, но возвращает только java.util.List.

Для этого вам нужен явный бросок.

24

Похоже, что SyndFeed не использует дженерики.

Вы можете либо иметь незащищенный бросок и подавление предупреждения:

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

или позвоните Collections.checkedList - хотя вы все равно нужно подавить предупреждение:

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

Поскольку они оба подавляют предупреждение, любые преимущества для одного или другим или предпочтением? Благодаря! Также: ли это приведение, если неконтролируемое подавление на месте? – 2014-05-13 23:44:24

+2

@Yar: Ну, `Collections.checkedList` предотвратит добавление каких-либо элементов, не связанных с SyndEntry. Я лично не использую `checkedList` много, но тогда я также не часто попадаю в эту неконтролируемую ситуацию приведения в любом случае ... – 2014-05-14 05:45:17

0

Если вы не хотите ставить @SuppressWarning ("unchecked") на каждый вызов sf.getEntries(), вы всегда можете сделать оболочку, которая вернет List.

См this other question

105

Это общая проблема при работе с предустановленным 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.

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)); 
0
SyndFeedInput fr = new SyndFeedInput(); 
SyndFeed sf = fr.build(new XmlReader(myInputStream)); 
List<?> entries = sf.getEntries();