2015-08-25 20 views
9

Creare una classe comeControllo tipo interrotto sull'acquisizione corrispondente con limite superiore?

public class Play { 
    public static void main(String[] args) throws Exception { 
     outer(Integer.class, inner("abc")); 
    } 

    static <C> void outer(Class<C> c, List<? super C> s){ 
    } 

    static <C> List<C> inner(C c) { 
     return null; 
    } 
} 

e compila in Java 8! (Sia in Eclipse 4.5 e JDK1.8_25) https://ideone.com/Q9JLHP

In Eclipse, tutti i limiti sono desunti correttamente, ma come potrebbe catturare Supplier<? super Integer>outer 's state mai soddisfatti con l'argomento Supplier<String> ??

Modifica: chiarito questo è specifico di Java 8 e ha reso l'esempio meno confuso.

+0

@ bayou.io È solo un tipo generico arbitrario che ho scelto per l'esempio. Sono sicuro che il compilatore non lo tratta in modo speciale qui. Aggiornerò l'esempio per evitare questa confusione. –

risposta

10

inner("abc") può, a discrezione del compilatore, essere interpretato come Supplier di qualsiasi supertipo di String. - per esempio,

Supplier<Object> inner = inner("abc"); 

funziona bene, perché è "abc"anche un Object. Ecco cosa sta succedendo qui: inner ti restituisce un Supplier<Object>.

+0

Ma questo comportamento sembra essere nuovo per Java 8. Qualsiasi riferimento al motivo per cui è stata apportata questa modifica? Perché ha rotto il controllo di tipo su 'assertThat() 'di Hamcrest, che è comunemente usato. –

+1

Java 8 ha [inferenza del tipo di destinazione] (http://openjdk.java.net/jeps/101), che consente di propagare le informazioni di inferenza sia verso il basso che verso l'alto. Questo è praticamente necessario per rendere lambda magicamente il tipo giusto per il loro contesto come una cosa generale. –

+2

Oltre ad aiutare le espressioni lambda, risolve i difetti che esistevano dall'introduzione di Generics, cioè come non si poteva scrivere 'Elenco l = Arrays.asList (42);' o 'Lista l = condizione? ...: Collections.emptyList(); ', ecc. Se interrompe il codice esistente, è il codice esistente che è difettoso in quanto lo stesso codice avrebbe passato il compilatore più vecchio quando il tipo dedotto sarà inserito manualmente, cioè qui dicendo' esterno (Integer.class, Play. inner ("abc")); ' – Holger

1

Inference sul inner richiede che C è un supertipo di Integer e String.

Che cos'è esattamente C? Questa è una storia complicata. Sia Integer e String sono Object, ovviamente. Ma entrambi sono anche Serializable! e anche Comparable<?> ....

Alla fine, non importa molto; tutto ciò che dobbiamo sapere è che si tratta di un "minimo limite superiore" di String e Integer, in qualsiasi modo sia defined.

+0

' C' non deve essere un supertipo di 'Integer' e' String'. La 'List' nella firma di' outer' deve solo contenere elementi di qualche supertipo non specificato di 'Integer' e' String'. –