Пожалуйста, не отсылайте людей к устаревшей информации. Немного более длинный поиск привел бы вас к более свежей версии: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html , которой 18 месяцев, а сейчас она во многих мест. Ответ на вопрос OP можно найти на lambdafaq.org/what-is-a-functional-interface , одной странице в FAQ, который я стараюсь поддерживать в актуальном состоянии в том, что до недавнего времени было быстро меняющимся языком и разработкой API.
Морис Нафталин
1
@MauriceNaftalin Вы также можете просто связать след Java , который постоянно обновляется командой разработчиков.
Брайан
1
Текущий термин - «функциональный интерфейс».
newacct
1
@MauriceNaftalin: Простите, я пропустил это. Несомненно, связался бы с этим, если бы нашел это.
Jon Skeet
Ответы:
142
Подводя итог ссылке, которую Джон опубликовал 1 на случай, если она когда-нибудь выйдет из строя, «SAM» означает «единственный абстрактный метод», а «SAM-type» относится к таким интерфейсам, как Runnable,Callable и т. Д. Лямбда-выражения, новая функция в Java 8, являются считается типом SAM и может быть свободно преобразован в них.
Например, с таким интерфейсом:
publicinterfaceCallable<T>{public T call();}
Вы можете объявить Callableлямбда-выражения следующим образом:
Callable<String> strCallable =()->"Hello world!";System.out.println(strCallable.call());// prints "Hello world!"
Лямбда-выражения в этом контексте в основном представляют собой синтаксический сахар. Они выглядят лучше в коде, чем анонимные классы, и менее строгие при именовании методов. Возьмите этот пример по ссылке:
Это создает Comparatorиспользование определенного метода, который не имеет того же имени, что иComparator.compare , что и, таким образом, вам не нужно следовать интерфейсу именования методов, и вы можете иметь несколько переопределений сравнения в классе, а затем создавать компараторы на лету через лямбда-выражения.
Идем глубже ...
На более глубоком уровне Java реализует их с помощью invokedynamicинструкции байт-кода, добавленной в Java 7. Я сказал ранее, что объявление Lambda создает экземпляр анонимного класса Callableили Comparableаналогичный ему, но это не совсем так. Вместо этого, при первом invokedynamicвызове, он создает обработчик функции Lambda с помощью LambdaMetafactory.metafactoryметода , а затем использует этот кешированный экземпляр в будущих вызовах Lambda. Более подробную информацию можно найти в этом ответе .
Этот подход сложен и даже включает в себя код, который может считывать примитивные значения и ссылки непосредственно из памяти стека для передачи в ваш код Lambda (например, чтобы обойти необходимость выделения Object[]массива для вызова вашей Lambda), но он позволяет будущие итерации реализации Lambda. заменить старые реализации, не беспокоясь о совместимости байт-кода. Если инженеры Oracle изменят базовую реализацию Lambda в более новой версии JVM, Lambdas, скомпилированные на более старой JVM, автоматически будут использовать новую реализацию без каких-либо изменений со стороны разработчика.
Ответы:
Подводя итог ссылке, которую Джон опубликовал 1 на случай, если она когда-нибудь выйдет из строя, «SAM» означает «единственный абстрактный метод», а «SAM-type» относится к таким интерфейсам, как
Runnable
,Callable
и т. Д. Лямбда-выражения, новая функция в Java 8, являются считается типом SAM и может быть свободно преобразован в них.Например, с таким интерфейсом:
Вы можете объявить
Callable
лямбда-выражения следующим образом:Лямбда-выражения в этом контексте в основном представляют собой синтаксический сахар. Они выглядят лучше в коде, чем анонимные классы, и менее строгие при именовании методов. Возьмите этот пример по ссылке:
Это создает
Comparator
использование определенного метода, который не имеет того же имени, что иComparator.compare
, что и, таким образом, вам не нужно следовать интерфейсу именования методов, и вы можете иметь несколько переопределений сравнения в классе, а затем создавать компараторы на лету через лямбда-выражения.Идем глубже ...
На более глубоком уровне Java реализует их с помощью
invokedynamic
инструкции байт-кода, добавленной в Java 7. Я сказал ранее, что объявление Lambda создает экземпляр анонимного классаCallable
илиComparable
аналогичный ему, но это не совсем так. Вместо этого, при первомinvokedynamic
вызове, он создает обработчик функции Lambda с помощьюLambdaMetafactory.metafactory
метода , а затем использует этот кешированный экземпляр в будущих вызовах Lambda. Более подробную информацию можно найти в этом ответе .Этот подход сложен и даже включает в себя код, который может считывать примитивные значения и ссылки непосредственно из памяти стека для передачи в ваш код Lambda (например, чтобы обойти необходимость выделения
Object[]
массива для вызова вашей Lambda), но он позволяет будущие итерации реализации Lambda. заменить старые реализации, не беспокоясь о совместимости байт-кода. Если инженеры Oracle изменят базовую реализацию Lambda в более новой версии JVM, Lambdas, скомпилированные на более старой JVM, автоматически будут использовать новую реализацию без каких-либо изменений со стороны разработчика.1 Синтаксис ссылки устарел. Взгляните на тропу Java по лямбда-выражениям, чтобы увидеть текущий синтаксис.
источник