2013-05-01 5 views
8

Kann jemand erklären, warum es auf der Zuweisungszeile eine Warnung wegen nicht typisierter Konversion gibt? Beachten Sie, dass bei X- oder Z-Zuweisungen keine Warnung angezeigt wird.Unerwartete ungeprüfte Konvertierungswarnung

public class Entity<T> 
{ 
    @SuppressWarnings("unchecked") 
    public <TX> Entity<TX> typed(Class<TX> type) 
    { 
     return (Entity<TX>) this; 
    } 

    @SuppressWarnings("unchecked") 
    public static <TX> Entity<TX> typed(Entity<?> entity, Class<TX> type) 
    { 
     return (Entity<TX>) entity; 
    } 

    public static void main(final String[] args) 
    { 
     final Entity<?> a = new Entity<Integer>(); 
     final Entity b = (Entity) a; 

     final Entity<Integer> x = a.typed(Integer.class); 
     final Entity<Integer> y = b.typed(Integer.class); 
     final Entity<Integer> z = typed(b, Integer.class); 
    } 
} 
+2

Ihre Entität 'b' ist nach der Umwandlung von' a' nicht typisiert, daher ist sie nicht typisiert, wenn Sie sie mit 'b.typed (Integer.class)' zurückkonvertieren.Generische Typen sind im Gegensatz zu Klassentypen; Sie werden nicht beibehalten, wenn sie downcasted werden. – Vulcan

Antwort

6

b ist vom Typ Entity, die ein Roh-Typ ist. Daher seine API sieht wie folgt aus:

public Entity typed(Class type) 

Sie sind also Entity-Entity<Integer> konvertieren. Der Compiler hat jede Korrelation zwischen dem Parameter type und der Art der zurückgegebenen Entität verloren, so dass keine Überprüfung mehr möglich ist.

es anders auszudrücken, könnten Sie verwenden:

final Entity<Integer> y = b.typed(String.class); 

... und nur noch die gleiche Warnung erhalten. Wenn Sie die gleiche Änderung mit x oder z versuchen, erhalten Sie stattdessen einen Kompilierungsfehler.

EDIT: Wie in den Kommentaren erwähnt, entfernt die Tatsache, dass Sie einen unformatierten Typ verwenden, alle Spuren von Generika.

Von JLS section 4.8:

Um mit nicht-generic Legacy-Code zu erleichtern Schnittstelle ist es möglich, als eine Art zu verwenden, um das Löschen (§4.6) eines parametrisierte Typ (§4.5) oder die Löschung eines Array-Typ (§10.1), dessen Elementtyp ein parametrisierter Typ ist. Ein solcher Typ wird als Rohtyp bezeichnet.

Und dann in section 4.6:

Typ Löschkarten auch die Signatur (§8.4.2) einen Konstruktor oder eine Methode mit einer Signatur, die keine parametrisierte Typen oder geben Sie Variablen hat. Das Löschen einer Konstruktor- oder Methodensignatur s ist eine Signatur, die aus dem gleichen Namen wie s und den Löschungen aller in s angegebenen formalen Parametertypen besteht.

+1

Beachten Sie, dass die "typisierte" Methode selbst parametrisiert ist. Es gibt zwei Typparameter. –

+4

@KonstantinKomissarchik: Das ist egal - wenn Sie eine Methode auf einem rohen Typ aufrufen, geht das alles weg. –

+0

Mit der Ausnahme, dass der Compiler nicht sagt, dass ich eine Methode für einen unformatierten Typ aufruft. Es sagt, dass ich eine ungeprüfte Konvertierung in der Zuordnung von Entität zu Entität mache. Der Typ wird vollständig durch TX angegeben. –

0

Sie "downcasting" a, Entfernen seiner Typkennung beim Zuweisen zu b. Da b jetzt nicht typisiert ist, erhalten Sie eine Warnung wegen nicht typisierter Konvertierung, da der Typ nicht mehr bekannt ist.

1

Aus der Erklärung:

final Entity<?> a = new Entity<Integer>(); 

a eingegeben wird, so der Aufruf der Methode ist a.typed(Integer.class) wird auch eingegeben.

In typed(b, Integer.class) funktioniert es, weil die Methode generisch ist.

Aber in

final Entity b = (Entity) a; 

Sie haben abgeschalteten Generika (für b durch die rohe-Typ anstelle der generic-Version von Entity verwendet wird), so der Aufruf b.typed(Integer.class) ist nicht typisiert. So bekommst du die Warnung.