Inkompatible Klassen von Java-Generics

8

Es scheint, ich stecke wieder mit Java-Generika fest. Hier ist was ich habe:

Paar Klassen:

class CoolIndex implements EntityIndex<CoolEntity>

class CoolEntity extends BaseEntity

Enum mit Klassen oben:

%Vor%

Funktion Ich muss mit der Verwendung von Ergebnis von getIndexCls() Funktionsaufruf aufrufen:

%Vor%

Das Problem ist, dass der Compiler sich über return CoolIndex.class; und return CoolEntity.class; beschwert und es mir nicht klar ist, warum ... Natürlich kann ich es in Class<I> (erster Fall) umwandeln, aber es scheint mir so, als ob ich es wäre versuchen, mein Missverständnis zu verschleiern und es fühlt sich nicht richtig an.

    
mr.nothing 26.04.2016, 15:17
quelle

2 Antworten

4

Das Problem mit getIndexCls besteht darin, dass die Typparameter als generische Klassen interpretiert werden können, die den Grenzen der Deklarationen entsprechen. Sie können denken, dass CoolIndex.class diese Grenzen erfüllt, und das tut es auch, aber ein Aufrufer der Methode kann ihre eigenen Typargumente liefern, die inkompatibel wären, z. B .:

%Vor%

Das würde die Typensicherheit unterbrechen, so dass der Compiler dies nicht zulässt. Sie können in Class<I> umwandeln, aber der Compiler warnt Sie aus demselben Grund vor einer ungeprüften Besetzung. Es wird kompiliert, aber es kann Laufzeitprobleme verursachen, wie ich beschrieben habe.

Andere Situationen können eine solche Situation lösen, indem Sie ein Class<I> -Objekt übergeben, damit die Typrückschlüsse richtig funktionieren, aber das verhindert den Punkt dieser Methode - es wird ein Class<I> -Objekt zurückgegeben.

Andere Situationen erfordern das Verschieben der generischen Typparameter von der Methode zur Klasse, aber Sie verwenden Enums, die nicht generisch sein können.

Die einzige Möglichkeit, etwas Ähnliches zu kompilieren, ist, das enum vollständig zu entfernen. Verwenden Sie eine abstrakte Klasse, damit Sie Typparameter auf Klassenebene deklarieren können. Instantiiere Konstanten mit den gewünschten Typargumenten.

%Vor%     
rgettman 26.04.2016, 15:46
quelle
1

Dies kann durch ein viel einfacheres Beispiel reproduziert werden:

%Vor%

Das Problem in einer solchen Deklaration <E extends BaseEntity> ist, dass Ihre Methode eine Instanz eines beliebigen Typs E zurückgibt, die der Aufrufer fragen sollte:

%Vor%

Dieser Code sollte kompilierungssicher sein, daher müssen Sie das Ergebnis Ihrer Methode in E

umwandeln %Vor%

In Ihrem Beispiel ist es ziemlich dasselbe, Sie behaupten, den Wert vom Typ Class<E> zurückzugeben:

%Vor%

Aber geben Sie eine konkrete Klasse SomeEntity.class zurück, die Class<CoolEntity> ist

OK, wie soll ich das beheben?
  1. Sie können den Typ cast return (Class<I>) CoolIndex.class; / return (Class<E>) CoolEntity.class;

  2. hinzufügen
  3. Sie können enum durch Klassen ersetzen, da enums nicht generisch sein können und Klassen können

  4. Sie können Generika vollständig entfernen, da es keinen großen Wert darin gibt

AdamSkywalker 26.04.2016 15:51
quelle

Tags und Links