2015-03-02 10 views
19

Sto utilizzando Android Studio 1.1.0.Avviso di assegnazione deselezionata

Questo fa sì che nessun avvertimento:

public static class A { 
    public Map<Integer, String> getMap() { 
     return null; 
    } 
} 

public static class B { 
    public void processA(A a) { 
     Map<Integer, String> map = a.getMap(); 
    } 
} 

Ma fare A generico:

public static class A<T> { 
    public Map<Integer, String> getMap() { 
     return null; 
    } 
} 

E questa linea:

Map<Integer, String> map = a.getMap(); 

si ottiene un avvertimento ora: "Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'.

Anche se la firma di getMap è totalmente indipendente da T e il codice non è ambiguo per quanto riguarda i tipi che contiene lo Map.

So che posso liberarmi di avvertimento da reimplementare processA come segue:

public <T> void processA(A<T> a) { 
    Map<Integer, String> map = a.getMap(); 
} 

Ma perché avrei dovuto farlo? Che cosa importa qui lo T?

Quindi, la domanda è - perché non digitare la cancellazione deve interessare non solo T (che è comprensibile - se sto passando un'istanza di A, T è uno sconosciuto), ma anche "hardcoded" firma generico come <Integer, String> in questo caso?

risposta

13

Nel suo secondo caso quando si esegue:

public void processA(A a) 

Che cosa si intende per A? Significa A<String> o A<List<String>> o cosa? Potresti non utilizzare nulla relativo al tipo di A, ma hey il compilatore non conosce questo fatto. Per il compilatore, solo A è un segno di panico.

Nel tuo caso, perché tu non specificamente necessario conoscere il tipo di A, è possibile:

public void processA(A<?> a) { 
    Map<Integer, String> map = a.getMap(); 
} 

Avere un tipo di argomento di A<?> mezzi, non specificamente cura il tipo di A e basta specificare una carta selvaggia. Significa: qualsiasi oggetto di A con qualsiasi tipo come farebbe il suo tipo generico. In realtà, significa che non conosci il tipo. È inutile perché non puoi fare nulla relativo a A in modo tipicamente valido come ? può essere praticamente qualsiasi cosa!

Ma secondo il vostro corpo metodo, rende tutto il senso del mondo di utilizzare A<?> perché nessun dove nel corpo è effettivamente necessario il tipo di A

+0

'Non potrebbe utilizzare tutto ciò che riguarda il tipo di A ma hey il compilatore non conosce questo fatto - beh, * potrebbe * conoscerlo abbastanza facilmente, basta dare un'occhiata all'implementazione di 'processA', non è difficile verificare che' T' sia irrilevante;) Vado con '' come suggerisci, ma sono deluso dal compilatore. –

+0

@KonradMorawski In un mondo ideale, solo "A" dovrebbe essere illegale e il codice non dovrebbe essere compilato. Ma è consentito per motivi di compatibilità con le versioni precedenti. Per una classe dichiarata come 'A ', il suo tipo generico è estremamente importante per fare qualsiasi cosa relativa a 'A'. Quindi non è permesso usare solo 'A' (infatti in Scala, è illegale usare solo' A') – Jatin

+0

Sì, immagino ... Non uso Scala, ma vengo dal lato C# del il mondo e i generici di Java sembrano scarpe troppo piccole. –

5

quando si intende accettare un A<T> di ogni possibile tipo T, ma non è necessario il T, questo è correttamente espresso utilizzando un carattere jolly e la scrittura A<?>. In questo modo permetterà di eliminare l'avviso nel codice:

public void processA(A<?> a) { 
    Map<Integer, String> map = a.getMap(); 
} 

Utilizzando il tipo nuda A non è trattata in modo equivalente. Come spiegato nel Java Language Specification, tipi prime come che non sono destinati ad essere utilizzati in nuovo codice:

conversione non registrato è utilizzato per consentire un agevole interazione di codice legacy, scritto prima l'introduzione di tipi generici, con le librerie che hanno subito una conversione per usare la genericità (un processo che chiamiamo generificazione). In tali circostanze (in particolare, i client di Collections Framework in java.util), il codice legacy utilizza i tipi non elaborati (ad esempio, Collection invece di Collection <String>). Le espressioni di tipi non elaborati vengono passate come argomenti ai metodi di libreria che utilizzano versioni parametrizzate di quegli stessi tipi dei tipi dei loro parametri formali corrispondenti.

Tali chiamate non possono essere considerate staticamente sicure sotto il sistema di tipi che utilizzano i generici. Rifiutare tali chiamate invaliderebbe grandi corpi di codice esistente e impedirebbe loro di usare versioni più recenti delle librerie. Ciò, a sua volta, scoraggerebbe i venditori di biblioteche dal trarre vantaggio dalla genericità. Per impedire tale svolta indesiderata di eventi, un tipo non elaborato può essere convertito in un'invocazione arbitraria della dichiarazione di tipo generico a cui si riferisce il tipo non elaborato. Mentre la conversione è sbagliata, è tollerata come una concessione alla praticità. In questi casi viene emesso un avviso non controllato.

Problemi correlati