Синтаксис описание
Lambda выражение состоит из следующих частей:
1. Список формальных параметров в запятой в скобках. Метод контроля. Примечание. Типы параметров в выражениях Lambda могут быть опущены; Кроме того, если есть только один параметр, кронштейны также могут быть опущены. Например, код, упомянутый в предыдущем разделе:
p -> p.getgender () == person.sex.male && p.getage ()> = 18 && p.getage () <= 25
2. Символ стрелки: ->. Используется для разделения параметров и функциональных тел.
3. Функциональный корпус. Состоящий из выражения или блока кода. В примере в предыдущем разделе это выражение использовалось:
p.getgender () == person.sex.male && p.getage ()> = 18 && p.getage () <= 25
Если вы используете выражение, время выполнения Java рассчитана и вернет значение выражения. Кроме того, вы также можете использовать оператор возврата в блоке кода:
p -> {return p.getgender () == person.sex.male && p.getage ()> = 18 && p.getage () <= 25; }Однако оператор возврата не является выражением. В выражениях Lambda утверждение должно быть заключено в кудрявые брекеты, но нет необходимости приласывать операторы в кудрявые скобки при простом вызове метода с пустым возвращающим значением, так что следующий метод написания также верен:
Электронная почта -> system.out.println (электронная почта)
Есть много сходств в объявлении выражений и методов Lambda. Следовательно, выражения Lambda также можно рассматривать как анонимные методы, то есть методы без определения имени.
Упомянутые выше выражения Lambda - это все выражения, которые используют только один параметр в качестве формального параметра. Следующий пример класса, Caulator, демонстрирует, как использовать несколько параметров в качестве формальных параметров:
пакет com.zhyea.zytools; public Class Calculator {interface Integermath {int aperice (int a, int b); } public int raybinary (int a, int b, integermath op) {return op.operation (a, b); } public static void main (string ... args) {calculator myApp = new Calculator (); IntegerMath adding = (a, b) -> a + b; System.out.println ("40 + 2 =" + myApp.operaintbinary (40, 2, добавление)); System.out.println ("20 - 10 =" + myApp.operaintbinary (20, 10, вычитание)); }}Метод OperingBinary в коде использует два целочисленных параметра для выполнения арифметических операций. Арифметическая операция здесь сама по себе является примером интерфейса Integermath. В вышеупомянутой программе две арифметические операции определяются с использованием выражений Lambda: добавление и вычитание. Выполнение программы будет распечатать следующий контент:
40 + 2 = 4220 - 10 = 10
Доступ к локальным переменным внешним классам
Подобно местным классам или анонимным классам, выражения Lambda также могут получить доступ к локальным переменным внешним классам. Разница в том, что нет необходимости рассматривать такие проблемы, как переопределение при использовании Lambda Expressions. Выражение Lambda - это просто лексическая концепция, что означает, что ему не нужно наследовать какие -либо имена от суперкласса, а также не вводит новые прицелы. То есть декларация в выражении Lambda имеет то же значение, что и объявление во внешней среде. Это продемонстрировано в следующем примере:
пакет com.zhyea.zytools; import java.util.function.consumer; открытый класс lambdascopetest {public int x = 0; класс Firstlevel {public int x = 1; void methodinfirstlevel (int x) {// Следующее оператор приведет к тому, что компилятор сообщает об ошибке «локальные переменные, упомянутые из выражения лямбды, должны быть окончательно или эффективно окончательно» // x = 99; Потребитель <Integer> myconsumer = (y) -> {System.out.println ("x =" + x); // утверждение a System.out.println ("y =" + y); System.out.println ("this.x =" + this.x); System.out.println ("lambdascopetest.tis.x =" + lambdascopetest.tis.x); }; myconsumer.accept (x); }} public static void main (string ... args) {lambdascopetest st = new lambdascopetest (); Lambdascopetest.firstlevel fl = St.new Firstlevel (); fl.methodinfirstlevel (23); }}Этот код выведет следующее:
x = 23y = 23this.x = 1lambdascopetest.his.x = 0
Если вы замените параметр y в выражении Lambda MyConsumer в примере с x, компилятор сообщит об ошибке:
Потребитель <Integer> myConsumer = (x) -> {// ....};Сообщение об ошибке компилятора: «Переменная x уже определена в методе MethodInFirstlevel (int)», что означает, что переменная x была определена в методе метода. Сообщается об ошибке, потому что выражение лямбда не вводит новую область. Следовательно, вы можете напрямую получить доступ к полям домена, методам и формальным параметрам внешнего класса в выражении Lambda. В этом примере выражение Lambda MyConsumer непосредственно обращается к параметру x метода MethodInFirstlevel. При доступе к участникам внешних классов это ключевое слово также используется напрямую. В этом примере это .x относится к Firstlevel.x.
Однако, как и локальные или анонимные классы, выражения Lambda могут получить доступ только к локальным переменным или внешним членам, объявленным окончательным (или эквивалентным к окончательному). Например, мы удаляем комментарий перед «x = 99» в методе метода примера кода:
// Следующее утверждение приведет к тому, что компилятор сообщит об ошибке «локальные переменные, упомянутые из выражения лямбды, должны быть окончательными или эффективно окончательными» x = 99; Потребитель <Integer> myconsumer = (y) -> {System.out.println ("x =" + x); // утверждение a System.out.println ("y =" + y); System.out.println ("this.x =" + this.x); System.out.println ("lambdascopetest.tis.x =" + lambdascopetest.tis.x); };Поскольку значение параметра x изменяется в этом утверждении, параметр x методики. Следовательно, компилятор Java сообщит о ошибке, такой как «локальные переменные, упомянутые из выражения лямбда, должны быть окончательными или эффективными окончательными», где выражение лямбда обращается к локальной переменной x.
Целевой тип
Как определить тип выражения лямбды? Давайте посмотрим на кодекс для фильтрации военнослужащих соответствующего возраста:
p -> p.getgender () == person.sex.male && p.getage ()> = 18 && p.getage () <= 25
Этот код использовался в двух местах:
Public Static Void Printpersons (список <Person> список, тестер контроля контроля) - Решение 3
public void printpersonswithpredicate (list <derson> ряд, предикат <derson> tester) - план VI
При вызове метода Printpersons этот метод ожидает параметр типа контроля. В настоящее время вышеуказанное выражение является выражением типа контроля. При вызове метода PrintPersOnsWithPredicate ожидается параметр типа Predicate <cerson>. В настоящее время то же самое выражение имеет тип предиката <человека>. Таким образом, тип, определяемый типом, ожидаемым методом, называется целевым типом (на самом деле, я думаю, что вывод типа в Scala здесь более подходит). Компилятор Java определяет тип выражения лямбды через контекст типа цели или положения при обнаружении выражения лямбды. Это означает, что выражения Lambda можно использовать только в тех случаях, когда компилятор Java может сделать вывод типа:
Целевой тип и параметры метода
Для параметров метода компилятор Java также должен полагаться на две языковые функции, чтобы определить целевой тип: перегрузка анализа и вывод параметров типа.
Взгляните на следующие два функциональных интерфейса (java.lang.runnable и java.util.concurrent.callable <v>):
Public Interface Runnable {void run (); } public interface callable <v> {v call (); }Метод runnable.run () не возвращает значение, в то время как метод callable.call () имеет его.
Предположим, что мы перегружаем метод вызова, например, следующее:
void inloke (runnable r) {r.run (); } <t> t invoke (callable <t> c) {return c.call (); }Итак, какой метод будет вызван в следующем утверждении:
String s = invoke(() -> "done");
Invoke (callable <t>) вызывается, потому что этот метод имеет возвращаемое значение, в то время как Invoke (Runnable <t>) не возвращает значение. В этом случае тип выражения Lambda (() -> «выполнен») является вызовочным <t>.
Сериализация
Если целевой тип выражения лямбды и типы параметров, которые он вызывает, являются сериализуемыми, то выражение лямбда также сериализуется. Однако, как и внутренние классы, сериализация выражений Lambda настоятельно не рекомендуется.