Digitare l'inferenza in Java 8


30

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:


47

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 .


2
"catturano questo in 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:" può ancora essere fatto con zucchero sintattico sostituendo tutto thisconMyClass.this
maniaco del cricchetto

4
Tutto ciò che va oltre l'assemblatore (e talvolta anche quello) è probabilmente zucchero sintattico. Ma le lambda non sono zucchero sintattico per le classi interne (non più). Servono un obiettivo simile e hanno alcune somiglianze, ma sotto il cofano sono (osservabilmente) diversi.
Joachim Sauer

1
"Le espressioni lambda sono semanticamente diverse dalle classi interne e sono implementate in modo diverso dalle classi interne.": Grazie per l'ottima spiegazione (+1). Ciò che non mi è ancora chiaro è perché l' agnada non sia stato implementato come zucchero sintattico per speciali classi anonime o, in altre parole, quale sia il vantaggio della complessità aggiuntiva introdotta dalla nuova semantica? Quale problema risolve questo problema che non può essere risolto con classi interne anonime? (Ma devo ancora guardare il link che hai pubblicato, forse troverò la risposta lì.)
Giorgio

1
@ Joachim Sauer: considererei lo zucchero sintattico una nuova sintassi per una semantica esistente. Quando viene introdotta una nuova semantica, penso che non si possa parlare di zucchero sintattico. In questo senso, non credo che si possa sostenere che tutto al di là dell'assemblatore sia zucchero sintattico.
Giorgio,

3
@Giorgio: riguardo al motivo per cui lambda non è solo zucchero sintattico per le classi interne anonime, si scopre che c'è stata una grande discussione su questo. Questa mail di Brian Goetz riassume la decisione: mail.openjdk.java.net/pipermail/lambda-dev/2011-August/… . TL; DR lascia la porta aperta per l'evoluzione futura e otteniamo prestazioni migliori oggi. Goetz sta effettivamente rispondendo a una domanda correlata, Gli oggetti lambdas sono? Ma se la risposta è No o forse Ciò implica che non possono essere zucchero per le classi interiori.
Stuart segna l'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.