2013-05-01 14 views
8

Qualcuno può spiegare perché c'è un avviso di conversione non tipizzato sulla linea di assegnazione? Si noti che non vi è alcun avviso sulle assegnazioni xoz.Avviso di conversione incontrollato non previsto

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

L'entità, 'b', non è tipizzata dopo il cast da' a', quindi non è tipizzata quando la si ricongiunge con 'b.typed (Integer.class)'.I tipi generici sono diversi dai tipi di classe; non vengono mantenuti quando "downcasted". – Vulcan

risposta

6

b è di tipo Entity, che è un tipo grezzo. Pertanto la sua API è simile al seguente:

public Entity typed(Class type) 

Così si sta convertendo Entity-Entity<Integer>. Il compilatore ha perso qualsiasi correlazione tra il parametro type e il tipo di entità restituita, quindi non può eseguire alcun controllo.

Per dirla in altro modo, è possibile utilizzare:

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

... e continuare a ricevere solo lo stesso avvertimento. Se provi la stessa modifica con x o z, riceverai invece un errore in fase di compilazione.

MODIFICA: come indicato nei commenti, il fatto che si sta utilizzando un tipo non elaborato rimuove tutte le tracce di generici.

Da JLS section 4.8:

Per facilitare l'interfacciamento con il codice legacy non generico, è possibile utilizzare come tipo la cancellazione (§4.6) di un tipo parametrico (§4.5) o la cancellazione di un tipo di array (§10.1) il cui tipo di elemento è un tipo parametrizzato. Un tal tipo è chiamato un tipo crudo.

E poi nel section 4.6:

Tipo cancellazione associa anche la firma (§8.4.2) di un costruttore o un metodo per una firma che non ha i tipi parametrici o digitare variabili. La cancellazione di un costruttore o di una firma del metodo è una firma composta dallo stesso nome di s e dalle cancellature di tutti i tipi di parametri formali dati in s.

+1

Si noti che il metodo "typed" è a sua volta parametrizzato. Ci sono due parametri di tipo. –

+4

@KonstantinKomissarchik: Non importa: quando si chiama un metodo su un tipo non elaborato, tutto scompare. –

+0

Tranne che il compilatore non sta dicendo che sto chiamando un metodo su un tipo non elaborato. Sta dicendo che sto effettuando una conversione non controllata nell'assegnazione dall'entità all'entità . Il tipo se completamente specificato da TX. –

0

Si sta "downcasting" a, rimuovendo il suo identificatore di tipo quando si assegna a b. Dato che b non è ancora stato creato, ricevi un avviso di conversione non tipizzato perché non conosce più il tipo.

1

dalla dichiarazione:

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

a viene digitato, quindi la chiamata al metodo è a.typed(Integer.class) è anche digitato.

In typed(b, Integer.class) funziona perché il metodo è generico.

Ma in

final Entity b = (Entity) a; 

voi hanno trasformato i generici-off (per b utilizzando il raw-tipo al posto del generico-versione di Entity) quindi l'invocazione b.typed(Integer.class) è tipizzato. Quindi ricevi l'avvertimento.

Problemi correlati