A introdução da nova notação lambda (consulte, por exemplo, este artigo ) no Java 8 exigirá algum tipo de inferência de tipo?
Se sim, como o novo sistema de tipos afetará a linguagem Java como um todo?
fonte
A introdução da nova notação lambda (consulte, por exemplo, este artigo ) no Java 8 exigirá algum tipo de inferência de tipo?
Se sim, como o novo sistema de tipos afetará a linguagem Java como um todo?
Há uma quantidade razoável de informações incorretas na resposta do catraca e no seu tópico de comentários. Vou responder aqui em uma resposta, já que um comentário é muito pequeno. Além disso, como essa é uma resposta, tentarei responder à pergunta original também. (Observe, no entanto, que eu não sou especialista em sistemas de tipos.)
Primeiro, as respostas curtas para a pergunta original são Sim e Não. Sim, o Java 8 terá consideravelmente mais inferência de tipo que o Java 7 e Não, não há um sistema de "novo" tipo no Java 8, embora haja algumas pequenas alterações .
O Java 8 ainda será digitado estaticamente e ainda terá a dicotomia entre classes e interfaces. Não há novos tipos, como tipos de função. O tipo de um lambda é essencialmente uma "interface funcional", que é uma interface comum com um único método abstrato.
As interfaces agora podem ter código na forma de métodos padrão, mas o modelo de herança única de classes e herança múltipla de interfaces permanece o mesmo. Existem alguns ajustes, é claro, como regras para resolução de métodos na presença de métodos padrão, mas os fundamentos são inalterados.
Qualquer tipo inferido por inferência de tipo pode ser gravado explicitamente. Para usar o exemplo de catraca ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
é basicamente açúcar para
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Portanto , a afirmação de sparkleshy "inferência de tipo não requer nenhuma extensão do sistema de tipos" está basicamente correta.
Mas, voltando ao açúcar sintático, repetirei minha afirmação de que uma expressão lambda não é açúcar sintático para uma classe interna anônima. Ratchet freak afirmou que uma expressão lambda é traduzida em uma instanciação anônima da classe interna, e Sparkleshy simplesmente reafirmou que um lambda é um açúcar sintático para uma classe interna anônima, mas essas declarações estão incorretas. Eles provavelmente são baseados em informações desatualizadas. As primeiras implementações de lambda implementaram lambdas dessa maneira, mas as coisas mudaram.
As expressões lambda são semanticamente diferentes das classes internas e são implementadas de maneira diferente das classes internas.
As expressões lambda são semanticamente diferentes das classes internas de duas maneiras. A avaliação de uma expressão lambda não precisa criar uma nova instância a cada vez. Eles também têm semântica de captura diferente, por exemplo, eles capturam isso de maneira diferente. Em uma classe interna, essa é a instância da classe interna, enquanto que em um lambda, essa é a instância anexa. Considere o seguinte:
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(); }
}
Em uma compilação lambda JDK 8 recente (usei b69 ), a saída será algo como o seguinte:
CaptureThis$1@113de03
outer
Além disso, as expressões lambda são implementadas de maneira completamente diferente das classes internas. Se você comparar a saída desmontada, verá que o código da classe interna é compilado diretamente para a criação e chama um construtor de CaptureThis $ 1, enquanto a expressão lambda é compilada para uma instrução dinâmica invocada que obtém um Runnable por meios não especificados. Para obter uma explicação completa de como isso funciona e por que, consulte JavaOne 2012 de Brian Goetz, converse sobre Lambda: A Peek Under The Hood .
this
porMyClass.this