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?
Si tel est le cas, quel sera l'impact du nouveau système de types sur le langage Java dans son ensemble?
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?
Si tel est le cas, quel sera l'impact du nouveau système de types sur le langage Java dans son ensemble?
Réponses:
Il y a pas mal d'informations incorrectes dans la 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 beaucoup plus d'inférence de type que Java 7, et Non, il n'y a pas de "nouveau" système de type 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 déclaration de « l' inférence de type ne nécessite pas d'extension du système de type » est fondamentalement correcte.
Mais pour revenir au sucre syntaxique, je répéterai mon affirmation qu'une expression lambda n'est pas du sucre syntaxique pour une classe interne anonyme. Ratchet freak a déclaré qu'une 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 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 cela différemment. Dans une classe interne, il s'agit de l'instance de classe interne, tandis que dans une lambda, il s'agit de 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 de Brian Goetz sur JavaOne 2012 Lambda: A Peek Under The Hood .
this
parMyClass.this