web-dev-qa-db-fra.com

Saisissez l'inférence dans Java 8

L'introduction de la nouvelle notation lambda (voir par exemple cet article ) dans Java 8 va-t-elle nécessiter une sorte d'inférence de type?

Dans l'affirmative, comment le nouveau système de types affectera-t-il la langue Java dans son ensemble?

30
Giorgio

Il y a pas mal d'informations incorrectes dans réponse de Ratchet Freak et dans son fil de commentaires. Je vais répondre ici dans une réponse, car un commentaire est trop petit. Aussi, puisque c'est une réponse après tout, je vais essayer de répondre à la question d'origine aussi. (Notez cependant que je ne suis pas un expert des systèmes de type.)

Premièrement, les réponses courtes à la question d'origine sont Oui et Non. Oui, Java 8 aura une inférence de type beaucoup plus importante que Java 7, et Non, il n'est pas un "nouveau" type de système dans Java 8, bien qu'il y ait quelques changements mineurs.

Java 8 sera toujours typé statiquement, et il aura toujours la dichotomie entre les classes et les interfaces. Il n'y a pas de nouveaux types tels que les types de fonction. Le type d'un lambda est essentiellement une "interface fonctionnelle" qui est une interface ordinaire avec une seule méthode abstraite.

Les interfaces peuvent désormais avoir du code sous la forme de méthodes par défaut, mais le modèle d'héritage unique des classes et d'héritage multiple des interfaces reste le même. Il y a bien sûr certains ajustements, comme les règles de résolution des méthodes en présence de méthodes par défaut, mais les fondamentaux restent inchangés.

Tout type déduit par l'inférence de type peut être écrit explicitement. Pour utiliser l'exemple de ratchet freak ,

Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });

est essentiellement du sucre pour

Collections.<MyClass>sort(list,
    (Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));

Donc sparkleshy la déclaration "l'inférence de type ne nécessite aucune extension du système de type" est fondamentalement correcte.

Mais pour revenir au sucre syntaxique, je répéterai ma déclaration selon laquelle une expression lambda n'est pas du sucre syntaxique pour une classe interne anonyme. Le monstre à cliquet a déclaré qu'un l'expression lambda est traduite en une instanciation de classe interne anonyme, et Sparkleshy a simplement réaffirmé qu'un lambda est du sucre syntaxique pour une classe interne anonyme, mais ces déclarations sont incorrectes . Ils sont probablement basés sur des informations obsolètes. Les premières implémentations lambda ont effectivement implémenté lambdas de cette façon, mais les choses ont changé.

Les expressions Lambda sont sémantiquement différentes des classes internes, et elles sont implémentées différemment des classes internes.

Les expressions lambda sont sémantiquement différentes des classes internes de deux manières. L'évaluation d'une expression lambda n'a pas besoin de créer une nouvelle instance à chaque fois. Ils ont également des sémantiques de capture différentes, par exemple, ils capturent ceci différemment. Dans une classe interne, ceci est l'instance de classe interne, tandis que dans une lambda, this est l'instance englobante. Considérer ce qui suit:

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(); }
}

Dans une construction lambda JDK 8 récente (j'ai utilisé b69 ), la sortie sera quelque chose comme ceci:

CaptureThis$1@113de03
outer

De plus, les expressions lambda sont implémentées complètement différemment des classes internes. Si vous comparez la sortie désassemblée, vous verrez que le code de la classe interne se compile directement à la création et appelle un constructeur de CaptureThis $ 1, tandis que l'expression lambda se compile en une instruction dynamique invoquée qui fournit un Runnable par des moyens non spécifiés. Pour une explication complète de la façon dont cela fonctionne et pourquoi, voir le discours JavaOne 2012 de Brian Goetz Lambda: Un coup d'œil sous le capot .

47
Stuart Marks