2008-12-15 6 views

Antwort

81

Da getEntries ein rohes zurück List, könnte es alles halten.

Der warnfreie Ansatz besteht darin, ein neues List<SyndEntry> zu erstellen und dann jedes Element des sf.getEntries() Ergebnisses in SyndEntry zu konvertieren, bevor es zu Ihrer neuen Liste hinzugefügt wird. Collections.checkedList tut nicht tun Sie dies für Sie überprüfen — obwohl es möglich gewesen wäre, es zu implementieren, um dies zu tun.

Indem Sie Ihren eigenen Vorschlag machen, erfüllen Sie die Garantiebedingungen von Java-Generics: Wenn ein ClassCastException ausgelöst wird, wird er einem Cast im Quellcode zugeordnet, nicht einem unsichtbaren Cast von der Compiler.

+9

Danke - das ist ein interessanter Einblick in die" Garantie "und die unsichtbare Besetzung des Compilers gegenüber einer Besetzung, die explizit in meinem eigenen Code gemacht wurde. – user46277

+1

Ja, der Wert von nicht-generalisierten Generika ist etwas begrenzt, aber das ist eine Sache, die es bietet. Nur um dies zu verdeutlichen, erfordert dies, dass Ihr Code ohne Sicherheitswarnungen für den Typ kompiliert wird. – erickson

+0

Hallo Erickson, ich stimme zu, dass dies in der Tat die beste Lösung ist. Überprüfen Sie meine Antwort http://stackoverflow.com/questions/367626/how-do-i-fix-the-expression-of-type-list-needs-unched-conversion/2848268#2848268 für eine generische Version dieser Lösung. –

7

Haben Sie dieschreiben 10?

Führt sf.getEntries Rückgabeliste oder List<SyndEntry>? Meine Vermutung ist, dass es List zurückgibt und das Ändern, um List<SyndEntry> zurückzukehren, wird das Problem beheben.

Wenn Teil einer Bibliothek ist, glaube ich nicht, dass Sie die Warnung entfernen können, ohne die @SuppressWarning("unchecked") Annotation zu Ihrer Methode hinzuzufügen.

+0

Sie können auch eine explizite Besetzung hinzufügen. – Uri

+2

Ein Cast erzeugt nur eine weitere Warnung, da der Code nicht typsicher ist. – erickson

+0

'SyndFeed' kommt von https://rometools.github.io/rome/ROMEReleases/ROME1.0Release.html. Das Problem scheint in neueren Versionen von Rom behoben zu sein, wie die, die unter https://mvnrepository.com/artifect/com.rometools/rome/1.9.0 – daloonik

1

Wenn man sich die javadoc für die Klasse aussehen SyndFeed (ich glaube, Sie beziehen sich auf die Klasse com.sun.syndication.feed.synd.SyndFeed), die Methode getEntries() nicht zurück java.util.List<SyndEntry>, liefert aber nur java.util.List.

Sie brauchen also eine explizite Besetzung dafür.

24

Es sieht aus wie SyndFeed verwendet keine Generika.

Sie könnte entweder eine unsichere Guss- und eine Warnung Unterdrückung haben:

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

oder Collections.checkedList nennen - obwohl Sie noch die Warnung zu unterdrücken brauchen werden:

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

gefunden wurden, da beide die Warnung unterdrücken, irgendwelche Vorteile zu einem oder dem andere oder eine Vorliebe? Vielen Dank! Auch: Ist die Besetzung notwendig, wenn die ungeprüfte Unterdrückung vorhanden ist? –

+2

@Yar: Nun, 'Collections.checkedList' verhindert später das Hinzufügen von Nicht-SyndEntry-Elementen. Ich persönlich benutze 'checkedList' nicht viel, aber dann komme ich auch nicht oft in diese unkontrollierte Castsituation ... –

0

Wenn Sie @SuppressWarning ("unchecked") nicht für jeden Aufruf von sf.getEntries() verwenden möchten, können Sie immer einen Wrapper erstellen, der List zurückgibt.

Siehe this other question

105

Dies ist ein häufiges Problem, wenn mit Pre-Java 5 APIs zu tun.Um die solution from erickson zu automatisieren, können Sie die folgende generische Methode erstellen:

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

Auf diese Weise können Sie tun:

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

Da diese Lösung überprüft, dass die Elemente haben in der Tat das richtige Element mittels eines Cast, es ist sicher und erfordert nicht SuppressWarnings.

+3

Bezüglich der von Bruno vorgeschlagenen Methode, würde dies die Anwendungsleistung bei Listen mit vielen Elementen nicht beeinträchtigen. Java müsste jeden einzelnen von ihnen werfen. – will824

+0

Wenn Sie Garantien wollen, sind das die Kosten. Gibt es eine andere, weniger teure Option? Offensichtlich, wenn Sie die zurückgegebene Methode für die aufgerufene Rohsammlung steuern oder sogar die Methode aufrufen oder auf die Sammlung mit einem Lazy-Demand-Ansatz zugreifen. Alles, was die gesamte Sammlung nach dem Methodenaufruf berücksichtigt? – dan

0

Noch einfacher

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

+0

Dann würden Sie für jedes Element in ArrayList mit ordnungsgemäßem Casting (Re-Casting?) Zur Nutzungszeit beschäftigen. – ingyhere

2

Wenn Sie Guava verwenden und alles, was Sie wollen, ist durch Ihre Werte iterieren:

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

Wenn Sie eine aktuelle Liste benötigen, können Sie

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

oder

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(); 
+1

Auch wenn der hier bereitgestellte Code das Problem löst, möchte ich Sie ermutigen, kurz zu erklären, warum das so ist. Bitte erläutern Sie, warum die veröffentlichte Antwort das Problem löst. – sbrattla