Wie kann es sein, dass Java in einer bestimmten Situation NICHT typsicher ist?

8

Heute habe ich ein sehr, sehr seltsames Verhalten der JVM gefunden, eine (normalerweise typensichere) List<Date> hat tatsächlich ein List<MyObject> zur Laufzeit gehalten!

Ich frage mich, wie das jemals passieren könnte, aber ich konnte nichts im Web finden.

Das ist die Situation: Ich arbeite mit Spring Data JPA 1.2.0 auf einem JBoss EAP 6.0 Server mit JRE 1.6.0_18-b07 .

In einer Spring Data JPA Repository -Klasse wurde versehentlich ein falscher Ergebnistyp im @Query -Ausdruck geschrieben. Es hätte sein sollen:

%Vor%

Aber war:

%Vor%

Also war das Ziel, eine Liste von Daten zu laden ( java.util.Date ), was gut funktioniert, wenn die Abfrage wie im ersten Code-Snippet richtig definiert ist.

Aber dieser Codierungsfehler führte zu folgendem Ergebnis: Zur Laufzeit wurde tatsächlich ein List<MyType> zurückgegeben, obwohl die Signatur der Methode ein List<Date> definiert. Auch in meinem Modell war ein Attribut von List<Date> ein List<MyType> enthalten. Ich habe es ausgepackt und konnte meinen Augen nicht trauen! Ich könnte sogar den Inhalt dieser Liste in eine JSP schreiben (ich erkannte dieses seltsame Verhalten nur, weil eine JSP nicht mehr angezeigt werden konnte, weil ein Spring Expression Language-Fehler beim Versuch, Übereinstimmung von MyType mit% co_de einzugeben, aufgetreten ist %, die natürlich abstürzen musste).

Hölle, soll ich jetzt meinen Glauben an die Typ-Sicherheit von Java verlieren?

Hat jemand jemals so ein Problem gehabt?

Existiert eine Erklärung dafür?

Und kann ich irgendetwas tun, um das zu beheben, oder ist das ein generelles Problem? Vielleicht eine andere Version der JRE, JBOSS, ...?

    
brainsheep 16.01.2013, 16:40
quelle

2 Antworten

9
  

Ich frage mich, wie das jemals passieren könnte, aber ich konnte nichts im Web finden.

Das passiert, weil Generika meist sind, die nur zur Kompilierzeit zur Verfügung stehen. Metadaten werden in Form von Typparametern, Feldern usw. einer Klasse verwaltet, aber zum Zeitpunkt der Ausführung sind Typargumente (meistens) verloren. Zum Beispiel:

%Vor%

Die JVM kann den Unterschied nicht erkennen - deshalb erhalten Sie eine Warnung, wenn Sie versuchen zu wirken:

%Vor%

Für den most -Teil hält der Compiler "normalen" Code unter Verwendung von Generics sicher. Aber wenn Sie Dinge wie ORMs haben, die Werte über Reflektion oder dynamischen Byte-Code liefern, geht all diese Sicherheit aus dem Fenster.

    
Jon Skeet 16.01.2013 16:44
quelle
5

Leider kann so etwas passieren, weil eine Löschung eingibt . Der Typ, den Sie in Ihrer Sammlung festgelegt haben, wird nur zur Kompilierungszeit und nicht zur Laufzeit überprüft.

Die Sache ist, dass Ihre Abfrage nicht kompiliert wird, also gibt es keine Möglichkeit, dass Java weiß, welche Art von Objekten es zurückgibt. Um diese Art von Verhalten zu vermeiden, erstelle ich immer Tests meiner Abfragen.

    
Caesar Ralf 16.01.2013 16:51
quelle

Tags und Links