「リスト型の式にはチェックされていない変換が必要です...」を修正するにはどうすればよいですか?


137

Javaスニペットでは:

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

最後の行は警告を生成します

「型の式Listに準拠するには、チェックされていない変換が必要ですList<SyndEntry>

これを修正する適切な方法は何ですか?

回答:


96

getEntriesrawを返すのでList、何でも保持できます。

警告のないアプローチは、新しいを作成しList<SyndEntry>sf.getEntries()結果の各要素をにキャストSyndEntryしてから、新しいリストに追加することです。Collections.checkedListではこのチェック行われません。ただし、そうするために実装することは可能でした。

独自のキャストを前もって行うことで、Javaジェネリックの「保証条件に準拠」します。a ClassCastExceptionが発生した場合、コンパイラによって挿入された目に見えないキャストではなく、ソースコードのキャストに関連付けられます。


9
ありがとう-これは、「保証」と、コンパイラーによって行われた目に見えないキャストと、自分のコードで明示的に行われたキャストについての興味深い洞察です。
user46277 2008

1
はい、未統一ジェネリックの価値は多少制限されますが、それはそれが提供するものの1つです。明確にするために、これにはコードがタイプセーフの警告なしでコンパイルされることが必要です。
エリクソン2008

こんにちはエリクソン、私はこれが確かに最良の解決策であることに同意します。このソリューションの一般的なバージョンについては、私の回答stackoverflow.com/questions/367626/…を確認してください。
Bruno De Fraine

115

これは、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


5
ブルーノによって提案された方法に関して、これは多くの要素を持つリストを持っているときにアプリケーションのパフォーマンスを損ないませんか?Javaはそれらすべてをキャストする必要があります。
will824

2
保証が必要な場合は、それがコストです。より安価な別のオプションはありますか?明らかに、呼び出されたrawコレクションを返すメソッド、またはメソッドを呼び出すか、レイジーデマンドアプローチを使用してコレクションにアクセスすることさえ制御できる場合。メソッドの呼び出し後にコレクション全体を考慮するものはありますか?
dan

28

SyndFeedジェネリックを使用していないようです。

安全でないキャストと警告の抑制のいずれかを行うことができます。

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

または、Collections.checkedListを呼び出します。ただし、警告を抑制する必要があります。

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

それらは両方とも警告を抑制するので、どちらか一方の利点、または好み?ありがとう!また、未チェックの抑制が行われている場合、キャストは必要ですか?
Dan Rosenstark、2014年

3
@Yar:まあ、Collections.checkedListSyndEntry以外の要素を後で追加することはできません。私は個人的にはあまり使用しませんcheckedListが、とにかくこの未チェックのキャスト状況に頻繁に入ることはありません...
Jon Skeet

9

あなたは書きましたSyndFeedか?

sf.getEntriesリストまたはを返しますかList<SyndEntry>?私の推測では、それは戻ってきてList、それを返すList<SyndEntry>ように変更すると問題が解決するでしょう。

SyndFeedがライブラリの一部である場合@SuppressWarning("unchecked")、メソッドに注釈を追加しないと警告を削除できないと思います。


明示的なキャストを追加することもできます。
ウリ

3
コードはタイプセーフではないため、キャストは別の警告を生成するだけです。
エリクソン2008


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

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

2
ここで提供されているコードで問題が解決されたとしても、なぜそれが行われるのかを簡単に説明することをお勧めします。投稿された回答が問題を解決する理由を説明してください。
sbrattla

1

クラスのjavadocを見るとSyndFeedcom.sun.syndication.feed.synd.SyndFeedおそらくクラスを参照していると思います)、メソッドgetEntries()はを返さずjava.util.List<SyndEntry>、ただを返しますjava.util.List

したがって、これには明示的なキャストが必要です。


0

@SuppressWarning( "unchecked")を各sf.getEntries()呼び出しに配置したくない場合は、いつでもListを返すラッパーを作成できます。

この他の質問を参照してください


0

さらに簡単に

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


次に、ArrayList <?>の各要素の使用時に適切なキャスト(再キャスト?)を処理します。
ingyhere 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.