Warum diese Generika nicht in OpenJDK7 kompilieren, sondern in OpenJDK6

8
%Vor%

kompiliert in OpenJDK6, aber in OpenJDK7 gibt es:

%Vor%

Beachten Sie, dass es in Zeile 50 eine Rawtype-Warnung gibt, da Alert parametrisiert werden muss. Wenn ich das tue, z.B. extends BaseController<Alert<Object>> , Code kompiliert. Aber ich kann das nicht tun, weil ich getModelClass () implementieren muss.

UPDATE: Das war ein Bug in Java 6-Implementierungen, der in Java 7 behoben wurde: Ссылка . (Und hier ist meine Frage zu Compiler-Devs: Ссылка )

    
Dzmitry Lazerka 11.03.2013, 03:16
quelle

3 Antworten

2

Die Frage ist, ob HasId<String> ein Supertyp des Rohtyps Alert ist. Die Spezifikation ist zu diesem Thema nicht sehr klar.

Im Geist von [4.8] sollten die Obertypen eines Rohtyps ebenfalls alle gelöschten Typen sein. Daher sollte Alert einen Obertyp HasId haben, aber nicht HasId<String> . Der Abschnitt spricht jedoch nur von "Super-Klassen / Interfaces", nicht von "Supertypen".

Im Geiste von [4.10] werden die Supertypen durch direkte Supertypen entdeckt. Es ist unklar, wie der Abschnitt auf Rohtypen angewendet wird. Es beabsichtigt wahrscheinlich zu bestimmen, dass rohe Alert einen direkten Supertyp HasStringId hat. Das scheint fair zu sein. Dann, weil HasId<String> ein direkter Supertyp von HasStringId ist, ist HasId<String> nach Transitivität ein Supertyp von Alert !

Die Verwirrung beruht auf der Tatsache, dass es tatsächlich zwei HasStringId -Typen gibt, einen normalen, einen rohen. Obwohl HasStringId an sich nicht generisch ist, hat es einen generischen Supertyp, daher ist es sinnvoll, über die rohe Version von HasStringId zu sprechen.

Die Spezifikation unterscheidet nicht zwischen normalem und rohem HasStringId . Das ist ein Versehen.

Angenommen, wir bezeichnen die rohe HasStringId als HasStringId' , dann macht [4.10] jetzt mehr Sinn. Die direkte Superschnittstelle von rohe Alert ist rohe HasStringId' . Die direkte Superschnittstelle von rohe HasStringId' ist rohe HasId . Daher ist HasId ein Supertyp von Alert , nicht HasId<String> .

Siehe Abschnitt 4 von JLS . Ich verbinde hier mit der vorherigen JLS, da JLS 7 schwerwiegende Bearbeitungsfehler in Abschnitt 4.10.2 hat

    
ZhongYu 11.03.2013 21:19
quelle
1

Es gibt eine Anzahl von dokumentierte Fälle von Java 7 Compilern, die strenger sind als Java 6 Compiler für verschiedene generische Nuancen. Diese Fälle beziehen sich oft auf die Spezifizierung der eigentlichen Sprachspezifikation. Der Fehler hat wahrscheinlich mit der Verwendung eines beliebigen Rohtyps zu tun, der im Wesentlichen "generisch" auf geerbte Typen verzichtet - ob es korrekt ist, ist jedoch fraglich.

BEARBEITEN: Ich konnte dieses Problem nicht in Liste der JDK 7 Inkompatibilitäten . Der Fehler ist reproduzierbar mit sun-jdk-1.7.0_10 , aber nicht mit dem Eclipse-Compiler (der in der Vergangenheit eine viel bessere Erfolgsbilanz als javac hat wenn es um generische Nuancen geht). Sie sollten einen Oracle-Fehler einreichen.

Hier ist ein möglicher Workaround:

%Vor%     
Paul Bellora 11.03.2013 15:03
quelle
1

Ich glaube, das hat damit zu tun, wie die Löschung in Abwesenheit von tatsächlichen Typparametern gehandhabt wird. Wenn ein parametrisierter Typ ohne Typparameter referenziert wird, werden alle Referenzen auf diese Parameter gelöscht.

In diesem Fall haben Sie einen parametrisierten Typ Alert , der ohne Typparameter verwendet wird. Dies löscht alle Typparameter auf Alert und seine Superklassen. Dadurch wird der Typparameter HasId in der extends-Klausel von HasStringId gelöscht. % Co_de% dann Unterklasse nicht Alert , da HasId<String> nicht mehr verlängert, sondern erstreckt HasStringId .

Paul B. die Abhilfe oder das unter vermeidet dieses Problem, indem sie immer HasId mit seiner Art Parameter angeben können.

%Vor%     
oconnor0 11.03.2013 21:49
quelle