"Liste türü ifadesinin denetlenmeyen dönüştürmeye ihtiyacı var ..." nasıl düzeltebilirim?


137

Java snippet'inde:

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

son satır uyarı oluşturur

"Türü ifadesi Listuyacak şekilde kontrolsüz dönüşüm ihtiyacıList<SyndEntry> "

Bunu düzeltmenin uygun bir yolu nedir?

Yanıtlar:


96

Çünkü getEntriesbir ham döndürürList , hiçbir şey tutabilir.

Uyarı içermeyen yaklaşım, yeni bir liste oluşturmak ve List<SyndEntry>ardından sf.getEntries()sonucun her bir öğesini SyndEntryyeni listenize eklemeden önce yayınlamaktır. bu kontrolü sizin için Collections.checkedListyapmaz - bunu yapmak mümkün olsa da.

Kendi döküm önünüzü yaparak, Java jeneriklerinin "garanti koşullarına uyuyorsunuz": a ClassCastExceptionyükseltilirse, derleyici tarafından eklenen görünmez bir dökümle değil, kaynak koddaki bir dökümle ilişkilendirilir.


9
Teşekkürler - bu "garanti" ve derleyici tarafından yapılan görünmez döküm hakkında açıkça kendi kodumda yapılan bir döküm hakkında ilginç bir fikir.
user46277

1
Evet, birleştirilmemiş jeneriklerin değeri biraz sınırlıdır, ancak bu sağladığı bir şeydir. Sadece açıklığa kavuşturmak için, kodunuzun tür güvenlik uyarıları olmadan derlenmesi gerekir.
erickson

Merhaba erickson, bunun gerçekten en iyi çözüm olduğuna katılıyorum. Bu çözümün genel bir sürümü için yanıtımı stackoverflow.com/questions/367626/… ' a bakın.
Bruno De Fraine

115

Java öncesi 5 API'leriyle uğraşırken bu yaygın bir sorundur. Çözümü erickson'dan otomatikleştirmek için aşağıdaki genel yöntemi oluşturabilirsiniz:

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

Bu şunları yapmanızı sağlar:

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

Bu çözüm, elemanların bir döküm vasıtasıyla gerçekten doğru eleman tipine sahip olup olmadığını kontrol ettiğinden, güvenlidir ve gerektirmez SuppressWarnings.


5
Bruno'nun önerdiği yönteme gelince, çok sayıda öğeye sahip Listeler varken uygulama performansına zarar vermez mi? Java'nın her birini dökmesi gerekirdi.
will824

2
Eğer garanti istiyorsanız, maliyet budur. Daha ucuz bir seçenek daha var mı? Açıkçası, çağrılan ham koleksiyon döndürme yöntemi üzerinde kontrole sahipseniz, hatta yöntemi çağırıyor veya tembel talep yaklaşımı kullanarak koleksiyona erişiyorsanız. Yöntem çağrıldıktan sonra tüm koleksiyonu dikkate alan bir şey var mı?
dan

28

Gibi görünüyor SyndFeed jenerik ilaç kullanmıyor.

Güvenli olmayan bir yayın ve uyarı bastırma özelliğiniz olabilir:

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

veya Collections.checkedList'i arayın - yine de uyarıyı bastırmanız gerekir:

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

İkisi de uyarıyı bastırdığından, birine ya da diğerine herhangi bir avantaj ya da bir tercih? Teşekkürler! Ayrıca: kontrolsüz bastırma yerinde ise kadro gerekli mi?
Dan Rosenstark

3
@Yar: Peki, Collections.checkedListdaha sonra SyndEntry olmayan öğelerin eklenmesini engelleyecektir. Şahsen checkedListçok fazla kullanmıyorum , ama yine de sık sık bu kontrolsüz döküm durumuna girmiyorum ...
Jon Skeet

9

Yazdın mı SyndFeed

sf.getEntriesListe veya geri dönüyor mu List<SyndEntry>? Benim tahminim geri döner Listve geri dönmek için değiştirirList<SyndEntry> sorunu çözecektir.

Eğer SyndFeedbir kütüphanenin bir parçası, sana eklemeden uyarıyı kaldırmak sanmıyorum @SuppressWarning("unchecked")senin yöntemine ek açıklama.


Ayrıca açık bir kadro ekleyebilirsiniz.
Uri

3
Kod türü güvenli olmadığından, bir yayın yalnızca başka bir uyarı oluşturur.
erickson

SyndFeedrometools.github.io/rome/ROMEReleases/ROME1.0Release.html adresinden gelir . Sorun olanlar bulunabilir gibi Roma'nın daha yeni sürümlerinde sabit gibi görünüyor mvnrepository.com/artifact/com.rometools/rome/1.9.0
daloonik

2

Guava kullanıyorsanız ve tüm yapmak istediğiniz değerleriniz arasında yineleme yapmaksa:

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

Gerçek bir listeye ihtiyacınız varsa kullanabilirsiniz

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

veya

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
Burada sağlanan kod sorunu çözse bile, kısaca bunu neden yaptığını açıklamanızı öneririm. Lütfen gönderilen cevabın sorunu neden çözdüğünü açıklayın.
sbrattla

1

Sınıf için javadoc bakarsanız SyndFeed(sanırım sınıfa atıfta bulunuyorsunuz com.sun.syndication.feed.synd.SyndFeed), getEntries () yöntemi geri dönmez java.util.List<SyndEntry>, ancak yalnızcajava.util.List .

Bunun için açık bir oyuncu kadrosuna ihtiyacınız var.


0

Her sf.getEntries () çağrısına @SuppressWarning ("işaretlenmemiş") koymak istemiyorsanız, her zaman Listeyi döndürecek bir sarıcı yapabilirsiniz.

Bu diğer soruyu görün


0

Daha da kolay

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


Daha sonra ArrayList <?> 'Deki her eleman için kullanım zamanında uygun döküm (yeniden döküm?) İle ilgilenirsiniz.
ingyhere
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.