Відповіді:
У відповіді на виродка храповика та у коментарях до нього є досить трохи невірної інформації . Я відповім тут у відповідь, оскільки коментар занадто малий. Крім того, оскільки це відповідь, зрештою, я спробую відповісти і на оригінальне запитання. (Однак зауважте, що я не є експертом із систем типів.)
По-перше, короткі відповіді на початкове запитання - так і ні. Так, у Java 8 буде набагато більше висновків про типи, ніж у Java 7, і ні, в Java 8 немає «нової» системи типу, хоча є деякі незначні зміни .
Java 8 все ще буде статично набрана, і вона все одно матиме дихотомію між класами та інтерфейсами. Немає нових типів, таких як типи функцій. Тип лямбда - це, по суті, "функціональний інтерфейс", який є звичайним інтерфейсом з єдиним абстрактним методом.
Тепер інтерфейси можуть мати код у вигляді методів за замовчуванням, але модель однонаспадкування класів та багатократного успадкування інтерфейсів залишається колишньою. Звичайно, є деякі коригування, такі як правила для вирішення методу за наявності методів за замовчуванням, але основи не змінюються.
Будь-який тип, на який можна зробити висновок про тип, може бути виписаний явно. Для використання прикладу храповика ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
в основному цукор для
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Таким чином, виразний вислів "умовивід типу не вимагає розширення системи типів" є в основному правильним.
Але повернусь до синтаксичного цукру, я повторю своє твердження, що лямбда-вираз не є синтаксичним цукром для анонімного внутрішнього класу. Ратчет урод заявив, що лямбда-вираз перекладається на анонімний внутрішній клас, і Спарклєші просто підтвердив, що лямбда - синтаксичний цукор для анонімного внутрішнього класу, але ці твердження є невірними. Вони, ймовірно, ґрунтуються на застарілій інформації. Ранні впровадження лямбда реалізували лямбдаси таким чином, але все змінилося.
Лямбда-вирази семантично відрізняються від внутрішніх класів, і вони реалізуються по-різному від внутрішніх класів.
Лямбдаські вирази паралельно семантично відрізняються від внутрішніх класів. Оцінюючи лямбда-вираз не потрібно створювати новий екземпляр кожен раз. Вони також мають різну семантику захоплення, наприклад, вони фіксують це по- різному. У внутрішньому класі, це є екземпляр внутрішнього класу, в той час як в лямбда, це є екземпляр вшита. Розглянемо наступне:
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(); }
}
У недавній лямбда-збірці JDK 8 (я використовував b69 ) вихід буде мати щось на зразок наступного:
CaptureThis$1@113de03
outer
Крім того, лямбда-вирази реалізуються зовсім інакше, ніж внутрішні класи. Якщо порівнювати розібраний вихід, ви побачите, що внутрішній код класу прямо компілюється до створення та виклику до конструктора CaptureThis $ 1, тоді як лямбда-вираз компілюється до викликаної динамічної інструкції, яка забезпечує Runnable через засоби, не визначені. Повне пояснення того, як це працює і чому, див. У бесіді Брайана Геца «JavaOne 2012» Lambda: Peek Under the Hood .
this
наMyClass.this