¿La introducción de la nueva notación lambda (ver, por ejemplo, este artículo ) en Java 8 va a requerir algún tipo de inferencia de tipos?
Si es así, ¿cómo afectará el nuevo sistema de tipos al lenguaje Java en su conjunto?
fuente
¿La introducción de la nueva notación lambda (ver, por ejemplo, este artículo ) en Java 8 va a requerir algún tipo de inferencia de tipos?
Si es así, ¿cómo afectará el nuevo sistema de tipos al lenguaje Java en su conjunto?
Hay bastante información incorrecta en la respuesta de Ratchet Freak y en su hilo de comentarios. Responderé aquí en una respuesta, ya que un comentario es demasiado pequeño. Además, dado que esta es una respuesta después de todo, intentaré responder la pregunta original también. (Sin embargo, tenga en cuenta que no soy un experto en sistemas de tipos).
Primero, las respuestas cortas a la pregunta original son Sí y No. Sí, Java 8 tendrá considerablemente más inferencia de tipos que Java 7, y No, no hay un sistema de tipos "nuevo" en Java 8, aunque hay algunos cambios menores. .
Java 8 seguirá estando estáticamente tipado y seguirá teniendo la dicotomía entre clases e interfaces. No hay nuevos tipos, como los tipos de función. El tipo de lambda es esencialmente una "interfaz funcional" que es una interfaz ordinaria con un único método abstracto.
Las interfaces ahora pueden tener código en forma de métodos predeterminados, pero el modelo de herencia única de clases y herencia múltiple de interfaces sigue siendo el mismo. Hay algunos ajustes, por supuesto, como las reglas para la resolución de métodos en presencia de métodos predeterminados, pero los fundamentos no cambian.
Cualquier tipo inferido por la inferencia de tipos podría escribirse explícitamente. Para usar el ejemplo de Ratchet Freak ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
es básicamente azúcar para
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Entonces , la afirmación de sparkleshy "la inferencia de tipos no requiere ninguna extensión del sistema de tipos" es básicamente correcta.
Pero para volver al azúcar sintáctico, repetiré mi afirmación de que una expresión lambda no es azúcar sintáctico para una clase interna anónima. Ratchet freak declaró que una expresión lambda se traduce en una instanciación anónima de clase interna, y Sparkleshy simplemente reafirmó que una lambda es azúcar sintáctica para una clase interna anónima, pero estas declaraciones son incorrectas. Probablemente se basan en información desactualizada. Las primeras implementaciones de lambda implementaron lambdas de esta manera, pero las cosas han cambiado.
Las expresiones lambda son semánticamente diferentes de las clases internas, y se implementan de manera diferente a las clases internas.
Las expresiones lambda son semánticamente diferentes de las clases internas en un par de formas. La evaluación de una expresión lambda no necesita crear una nueva instancia cada vez. También tienen diferentes semánticas de captura, por ejemplo, capturan esto de manera diferente. En una clase interna, esta es la instancia de clase interna, mientras que en una lambda, esta es la instancia de cierre. Considera lo siguiente:
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(); }
}
En una reciente compilación JDK 8 lambda (utilicé b69 ), el resultado será algo similar a lo siguiente:
CaptureThis$1@113de03
outer
Además, las expresiones lambda se implementan de manera completamente diferente a las clases internas. Si compara la salida desensamblada, verá que el código de clase interno compila directamente a la creación y llama a un constructor de CaptureThis $ 1, mientras que la expresión lambda compila a una instrucción invocada dinámica que proporciona un Runnable a través de medios no especificados. Para una explicación completa de cómo funciona esto y por qué, vea la charla de Brian Goetz en JavaOne 2012 Lambda: A Peek Under The Hood .
this
conMyClass.this