Questions & Answers

Pierced
I'm new here

Umgang mit Generics bei EditorValue

Hallo,

Es geht um das Interface EditorValue<T>.

Um direkt einzusteigen, hier ein Code-Auszug:

 // key enthaelt einen Bezeichner einer Editor-Komponente           

for (String key : myMap.keySet()) {

            // (!) EditorValue is a raw type. 

            EditorValue editorValue = data.get(key).getEditor();


            try {


// (!) Type safety: The method set(Language, Object) belongs to the raw type EditorValue

                editorValue.set(masterlanguage, scriptData.get(key).getEditor().get(masterlanguage));


            } catch (InvalidValueException e) {


//...

            }


}

Die beiden mit :smileyalert: markierten Stellen werden von Eclipse berechtigermaรŸen bemรคngelt, weil man sich รผber Generics hinwegsetzt. Sie werden ja durch das Interface EditorValue<T> hier gefordert.

Da wir รผber eine Collection von Bezeichnern von Editor-Komponenten iterieren, ist jedoch der Typ des konkreten EditorValue unklar, so dass man nicht auf bestimmte konkrete EditorValue-Typen (z.B. TextEditorValue) casten darf.

Meine Fragen:

Gibt es einen Weg, um diesen Fall elegant zu lรถsen, ohne auf @SuppressWarnings oder eine "hundertfache" instanceof-Behandlung zurรผckgreifen zu mรผssen?

Besten Dank

Georg

9 Replies
Peter_Jodeleit
Crownpeak employee

รœber "editorValue.getValueType().cast(..)", am besten รผber eine Hilfsmethode:

public <T> void setValue(final EditorValue<T> editorValue, final Language language, final Object value) throws InvalidValueException {

    editorValue.set(language, editorValue.getValueType().cast(value));

}

Hier kann natรผrlich eine ClassCastException fliegen, wenn die aufrufende Stelle eine ungรผltigen Werte-Typ liefert. Es muss also der Aufrufer sicherstellen, das nur korrekte Kombinationen benutzt werden.

Zu Generics kann ich folgende Web-Seite empfehlen: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

Peter

Ja die Angelika kenn' ich, fรผr mich das weiblich Pendant zu Josh Bloch ;-).

Danke fรผr den Tipp, ich werde ihn ausprobieren.

0 Kudos

Sorry,

ich muss hier nochmal einhaken und nachhaken.

Folgender Code:

Listable bodies = page.getChildren(Body.class);
for (Body body : bodies) {
Listable<Section> sections = body.getChildren(Section.class);
...
}

Jetzt ist es so, dass getChildren einen Rรผckgabewert Listable<Section> hat.

Jedoch ist Section an und fรผr sich generisch (ein Umstand รผbrigens, den ich nicht verstehe, denn was fรผr unterschiedliche Dinge enthรคlt so eine Section? In der Regel ist es auรŸerdem kein beliebiges "T" fรผr Section<T>, sondern ein Section<T extends SectionTemplate).

Aber zurรผck zur Frage:

Dieser Code lรคsst sich nur dann ohne Warnung anfรผhren, wenn man "@SuppressWarnings("rawtypes")" verwendet.

Wie unschรถn! Und das vermutlich nur, weil getChildren eine ungenerische Section zurรผckliefert.

Vermutlich habe ich mir die Antwort jetzt schon selbst vorweg genommen, daher:

Wรคre es mรถglich die API so zu aktualisieren, dass getChildren ebenfalls generisch arbeitet? In dem Zug wรคre es fรผr mich auch ausreichend, hier statt einem "Listable" eine echte List<Section<T>>  zurรผckzubekommen.

Danke... und jetzt dรผrft ihr mich teern und federn.

0 Kudos

Im Codebeispiel fehlt der generische Typ fรผr das erste Listable:

Listable<Body> bodies = page.getChildren(Body.class);

Damit sollte auch die Warnung verschwinden.

Die Typisierung von Section bezieht sich auf das Template (es gibt Sections fรผr Absatztemplates und fรผr Tabellentemplates).

Peter
0 Kudos

Hallo Peter,

Die Typisierung von Section bezieht sich auf das Template (es gibt Sections fรผr Absatztemplates und fรผr Tabellentemplates).

Ah - vor dem Hintergrund macht die Typisierung an der Stelle schon mehr Sinn. Sehe gerade dass SectionTemplate durch TableTemplate erweitert wird.

Hier nochmal der SourceCode

Listable<Body> bodies = page.getChildren(Body.class);

for (Body body : bodies) {

// @SuppressWarnings("rawtypes")

  Listable<Section> sections = body.getChildren(Section.class);

  // ^^^^^^^^

    for (Section<?> section : sections) {..}

}

Die markierte Zeile wird nachwievor gelb mit dem Hinweis auf "Section is a raw type." bemรคngelt. Meines Erachtens liegt das daran, dass body.getChildren keinen eine einfache Section, zurรผckgibt, jedoch nicht Section<T>.

0 Kudos

Hallo,

Georg Stach schrieb:

Die markierte Zeile wird nachwievor gelb mit dem Hinweis auf "Section is a raw type." bemรคngelt. Meines Erachtens liegt das daran, dass body.getChildren keinen eine einfache Section, zurรผckgibt, jedoch nicht Section<T>.

das ist technisch auch leider nicht anders mรถglich, weil hier die Klasse als Parameter den Rรผckgabetyp bestimmt. Und Klassen kann man so in Java nicht parameterisieren.

GruรŸ

Stefan

0 Kudos

das ist technisch auch leider nicht anders mรถglich, weil hier die Klasse als Parameter den Rรผckgabetyp bestimmt. Und Klassen kann man so in Java nicht parameterisieren

Wรผrde ich so nicht unterschreiben. Eine Signatur wie diese sollte es tun:

public <T> Listable<? extends T> getChildren(Class<? extends T> clazz)

0 Kudos

Das ist sicherlich richtig. Parameterisiert die Klasse natรผrlich nicht, aber es wรผrde das "Warning" Problem lรถsen. Eine Kleinigkeit fehlt noch in der Signatur, die dann so aussรคhe (betrifft im รผbrigen auch weitere API-Methoden dieser Art):

public <T extends StoreElement> Listable<? extends T> getChildren(Class<? extends T> clazz)

Der ร„nderung entgegen steht allerdings, dass dadurch zahlreiche Code-Stellen quellinkompatibel werden wรผrden, was im Rahmen der API natรผrlich nicht machbar ist (das รผbliche API Problem). Fรผr den Gewinn (ein Warning weniger) lohnt die ร„nderung jedenfalls nicht.

GruรŸ

Stefan

.. dass dadurch zahlreiche Code-Stellen quellinkompatibel ..

Ja, das sehe ich ein.

Dennoch, vielleicht ist es als Anregung hilfreich. Denn gerade weil es nicht die einzige Stelle in der API ist, die inkonsistent ist, kรถnnte man hier รผber eine Anpassung nachdenken.

Dann natรผrlich mit einem MajorRelease (ich will keine Nummern nennen Smiley Wink)...

0 Kudos

Type a product name