2013-01-10 5 views
6

Ho trovato un po 'di codice generico e mi ha messo in dubbio sul suo funzionamento. Non capisco dove si ottiene il tipo generico utilizzato per T. Questo è un esempio semplificato, ma non riesco ancora a capire come questo sia un codice Java valido.Da dove viene inferta questa funzione Java dal suo tipo generico?

public static void main(String[] args) { 
    System.out.print(get()); 
} 

public static <T> T get() 
{ 
    return (T) getObj(); 
} 

public static Object getObj() 
{ 
    return Boolean.FALSE; 
} 
+0

Vedere http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.7 – SLaks

+0

Si dovrebbe vedere un avvertimento del compilatore su un cast non controllato da 'Object per 'T'. – GriffeyDog

risposta

3

inferenza di tipo accade basa sul callsite.

Tuttavia, l'inferenza di tipo si applica solo ai tipi restituiti se il valore di ritorno è assegnato a una variabile. Questo è scritto nel spec

Se il risultato metodo di verifica in un contesto in cui sarà soggetta alla conversione assegnazione, quindi [...]

In caso contrario, tutti i parametri di tipo irrisolti diventano sempre Object.
Nel tuo esempio, funzionerà, perché c'è un sovraccarico print(Object).

D'altra parte, un'occhiata a questo codice:

print(get()); 

public void print(Boolean x) { } 

public <T> T get() { 
    return (T) Boolean.FALSE; 
} 

questo darà un errore di compilazione, perché il compilatore deduce get() come tornare Object prima di guardare print().

+0

è anche soggetta alla conversione dell'assegnazione. in Java8, l'inferenza di tipo impiegherà più informazioni contestuali. – irreputable

1

Nel codice che hai scritto T è non vincolato a nulla. Java assegnerà un tipo a T ogni volta che invocherai il metodo get e guarderà il tipo che ti aspetti di riavere ... ma sembra che funzioni solo se dichiari esplicitamente quale tipo stai aspettando. Guardate il seguente esempio:

public static void jump(String a) { 
} 

public static <T> T get() { 
    return (T) null; 
} 

public static void main(String[] args) { 
    //This works quite well, generic parameter T is inferred to be String 
    String blah = get(); 
    jump(blah); 
} 

D'altra parte

public static void jump(String a) { 
} 

public static <T> T get() { 
    return (T) null; 
} 

public static void main(String[] args) { 
    //This doesn't work, Java does not bind T to anything hence Object is used... and no jump for object is found 
    jump(get()); 
} 

Almeno questo è come funziona su Java 6.

+0

Qual è la regola che significa che sceglie 'print (Object)' piuttosto che 'print (String)'? –

+1

Va bene, allora cosa succede se non ho provato a stamparlo e l'ho chiamato direttamente. public static void main (String [] args) { get(); } Da dove viene inferito da allora? – Deadron

+0

Mi sbagliavo, immagino che T non sia infernale e legato a nulla. Quindi Object viene utilizzato perché è la cosa più astratta che Java possa gestire. Modificare la mia risposta La dichiarazione di risposta – Claudio

Problemi correlati