L'introduzione della nuova notazione lambda (vedi ad esempio questo articolo ) in Java 8 richiederà qualche tipo di deduzione di tipo?
In tal caso, in che modo il nuovo sistema di tipi avrà un impatto sul linguaggio Java nel suo insieme?
L'introduzione della nuova notazione lambda (vedi ad esempio questo articolo ) in Java 8 richiederà qualche tipo di deduzione di tipo?
In tal caso, in che modo il nuovo sistema di tipi avrà un impatto sul linguaggio Java nel suo insieme?
Risposte:
Ci sono un bel po 'di informazioni errate nella risposta di maniaco del cricchetto e nel suo thread di commenti. Risponderò qui in una risposta, poiché un commento è troppo piccolo. Inoltre, dal momento che questa è una risposta, cercherò di rispondere anche alla domanda originale. (Si noti tuttavia che non sono un esperto di sistemi di tipo.)
Innanzitutto, le risposte brevi alla domanda originale sono Sì e No. Sì, Java 8 avrà una maggiore deduzione dei tipi rispetto a Java 7 e No, non esiste un "nuovo" sistema di tipi in Java 8, sebbene ci siano alcune piccole modifiche .
Java 8 sarà ancora tipizzato staticamente e avrà ancora la dicotomia tra classi e interfacce. Non ci sono nuovi tipi come tipi di funzione. Il tipo di lambda è essenzialmente una "interfaccia funzionale" che è un'interfaccia ordinaria con un singolo metodo astratto.
Le interfacce ora possono avere il codice sotto forma di metodi predefiniti, ma il modello di ereditarietà singola delle classi e eredità multipla delle interfacce rimane lo stesso. Ci sono alcuni aggiustamenti, ovviamente, come le regole per la risoluzione dei metodi in presenza di metodi predefiniti, ma i fondamenti sono invariati.
Qualsiasi tipo dedotto dall'inferenza del tipo potrebbe essere scritto esplicitamente. Per usare l' esempio del maniaco del cricchetto ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
è fondamentalmente zucchero per
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Quindi l'affermazione di sparkleshy "l'inferenza di tipo non richiede alcuna estensione del sistema di tipi" è sostanzialmente corretta.
Ma per tornare allo zucchero sintattico, ripeterò la mia affermazione che un'espressione lambda non è zucchero sintattico per una classe interna anonima. Il mostro di Ratchet ha affermato che un'espressione lambda è tradotta in un'istanza anonima della classe interna e Sparkleshy ha semplicemente ribadito che una lambda è zucchero sintattico per una classe interna anonima, ma queste affermazioni sono errate. Probabilmente si basano su informazioni obsolete. Le prime implementazioni lambda hanno implementato lambda in questo modo, ma le cose sono cambiate.
Le espressioni lambda sono semanticamente diverse dalle classi interne e sono implementate in modo diverso dalle classi interne.
Le espressioni lambda sono semanticamente diverse dalle classi interne in un paio di modi. La valutazione di un'espressione lambda non deve necessariamente creare una nuova istanza ogni volta. Essi hanno anche diverse semantiche di cattura, per esempio, catturano questo modo diverso. In una classe interna, questa è l'istanza della classe interna, mentre in una lambda, questa è l'istanza che la racchiude. Considera quanto segue:
public class CaptureThis {
void a(Runnable r) { r.run(); }
void b() {
a(new Runnable() { public void run() { System.out.println(this); }});
a(() -> System.out.println(this));
}
public String toString() { return "outer"; }
public static void main(String[] args) { new CaptureThis().b(); }
}
In una recente build lambda JDK 8 (ho usato b69 ), l'output sarà simile al seguente:
CaptureThis$1@113de03
outer
Inoltre, le espressioni lambda sono implementate in modo completamente diverso dalle classi interne. Se confronti l'output disassemblato, vedrai che il codice della classe interna si compila in modo diretto alla creazione e chiama a un costruttore di CaptureQuesto $ 1, mentre l'espressione lambda si compila in un'istruzione invocata che procura un Runnable attraverso mezzi non specificati. Per una spiegazione completa di come funziona e perché, vedi JavaOne 2012 di Brian Goetz, Lambda: A Peek Under The Hood .
this
conMyClass.this