2016-08-26 2 views
4

Ich möchte eine schnelle und dreckige Helferklasse schreiben, die meine Objekte schnell speichern kann. Deshalb benutze ich Ormlite.Inline-Klasse, die einen Typparameter erweitert

Ich möchte keine Anmerkungen zu meinen Klassen hinzufügen, daher versuche ich, einen Wrapper im laufenden Betrieb ohne irgendwelche Bytecode-Bibliotheken hinzuzufügen.

<T> void save(T o) { 
    @DatabaseTable 
    class wrap extends T { 
     @DatabaseField(generatedId = true) 
     public Long id; 
    } 

    try { 
     Dao<T, Long> d = (Dao<T, Long>) getClassDao(o.getClass()); 
     TableUtils.createTableIfNotExists(connectionSource, o.getClass()); 
     d.createOrUpdate(o); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

Das Problem ist class wrap extends T - warum ist es nicht möglich T zu verlängern?

Antwort

3

Dies ist eine seltsame, aber interessante Frage! Es ist schwierig, eine genaue und erschöpfende Antwort zu geben. Es gibt wahrscheinlich viele verschiedene Gründe, aber ich denke, das folgende ist das wichtigste:

Nur eine Version von save wird jemals vom Compiler generiert werden. Für class wrap extends T zu arbeiten, müsste der Parameter T eine andere konkrete Klassen für jede Verwendung von save mit einem anderen Typ sein, aber das ist nicht, wie Generika arbeiten. save ist nur einmal kompiliert, und innerhalb saveT ist ein Typparameter, kein konkreter Typ. (Dies ist etwas verwandt mit, aber anders als Typ löschen, siehe unten.)

Andere Grund ist type erasure. Generische Typen in Java gibt es nur unter Kompilierzeit. Eine Klasse in Java dagegen hat eine Laufzeitdarstellung (im Gegensatz zu zB C++). Daher besteht keine Möglichkeit, dass die Laufzeitdarstellung einer Klasse aus dem Nur-Kompilierzeit-Konstrukt generiert werden kann, das ein generischer Typ ist.

1

Weil T könnte endgültig sein. Finale Klassen können nicht verlängert werden.

Zumindest ist dies ein logischer Grund, der die Erweiterung eines generischen Typs verbietet. Der technische Hintergrund wird in anderen Antworten erläutert.

+0

kann ich T als nicht-final deklarieren? – wutzebaer

+0

Es ist wahr, aber es geht nicht darum, endgültig zu sein. Es geht darum, * generisch * zu sein. 'T' könnte zur Laufzeit eine beliebige Klasse sein. Aber 'wrap' wird nur einmal kompiliert. Siehe Antwort von @Lii –

2

<T> ist ein generischer Typ, keine echte Klasse. Ein generischer Typ ist ein Kompilierzeitkonzept, es wird zur Laufzeit gelöscht, während eine Klasse ein Laufzeitkram ist und einen entsprechenden Bytecode hat. Sie können keine Unterklasse des generischen Typs <T> deklarieren, da der Compiler keine Ahnung hat, was diese Superklasse ist

Verwandte Themen