1 ответ:
подведем итоги ссылку Джон выложил1 в случае, если он когда-либо пойдет вниз, "SAM" означает "один абстрактный метод", а "SAM-тип" относится к интерфейсам, таким как
Runnable,Callableи т. д. Лямбда-выражения, новая функция в Java 8, считаются типом SAM и могут быть свободно преобразованы в них.например, с таким интерфейсом:
public interface Callable<T> { public T call(); }вы можете объявить
Callableиспользование лямбда-выражений, таких как это:Callable<String> strCallable = () -> "Hello world!"; System.out.println(strCallable.call()); // prints "Hello world!"лямбда-выражения в данном контексте в основном являются просто синтаксическим сахаром. Они выглядят лучше в коде, чем анонимные классы, и менее ограничивают именование методов. Возьмите этот пример из ссылки:
class Person { private final String name; private final int age; public static int compareByAge(Person a, Person b) { ... } public static int compareByName(Person a, Person b) { ... } } Person[] people = ... Arrays.sort(people, Person::compareByAge);это создает
Comparatorиспользуя определенный метод, который не имеет того же имени, что иComparator.compare, таким образом, вам не нужно следовать именованию интерфейса методов, и вы можете иметь несколько переопределений сравнения в классе, а затем создать компараторы на лету через лямбда-выражения.Идем Дальше...
на более глубоком уровне, Java реализует их с помощью
invokedynamicбайт-код инструкция добавлена в Java 7. Я уже говорил, что объявление лямбда создает экземплярCallableилиComparableпохоже на анонимный класс, но это не строго правда. Вместо этого, в первый разinvokedynamicвызывается, он создает обработчик лямбда-функции с помощьюLambdaMetafactory.metafactoryметод, затем использует этот кэшированный экземпляр в будущих вызовах лямбды. Более подробную информацию можно найти в ответ.этот подход является сложным и даже включает в себя код, который может считывать примитивные значения и ссылки непосредственно из стековой памяти для передачи в ваш лямбда-код (например, чтобы обойти необходимость выделения
Object[]массив для вызова вашего лямбда), но он позволяет будущим итерациям реализации лямбда заменять старые реализации без приходится беспокоиться о совместимости байт-кода. Если инженеры Oracle изменят базовую реализацию Lambda в более новой версии JVM, lambdas, скомпилированные на более старой JVM, автоматически будут использовать новую реализацию без каких-либо изменений со стороны разработчика.
1 синтаксис ссылки устарел. Взгляните на Лямбда-Выражения Java Trail чтобы увидеть текущий синтаксис.
Comments