English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Основной учебник Java

Java Управление потоком

Java Массивы

Java Ориентированность на объекты (I)

Java Ориентированность на объекты (II)

Java Ориентированность на объекты (III)

Обработка исключений Java

Java Список (List)

Java Queue (очередь)

Java Map коллекции

Java Set коллекции

Java Вход/Выход (I/O)

Java Reader/Writer

Другие темы Java

Java Lambda-выражения

Java 8 новые возможности

Lambda выражения, также известные как closures, являются одной из самых важных новых функций, которые推动了 выпуск Java 8.

Lambda позволяет передавать функцию в качестве параметра метода (функция передается в метод как параметр).

Использование lambda выражений делает код более кратким и компактным.

Синтаксис

Синтаксис lambda выражений выглядит следующим образом:

(parameters) -> expression
или
(parameters) -> { statements; }

Вот важные характеристики lambda выражений:

  • Дополнительное указание типа:Тип параметра не нужно указывать, компилятор может определить его значение автоматически.

  • Дополнительные скобки round parentheses:При одном параметре не нужно определять скобки round parentheses, но при нескольких параметрах они необходимы.

  • Дополнительные скобки curly braces:Если тело выражения содержит только одно предложение, использование скобок curly braces не требуется.

  • Дополнительный ключ return:Если тело выражения содержит только один выражение, компилятор автоматически возвращает его значение, и скобки curly braces нужны для указания, что выражение возвращает числовое значение.

Пример lambda выражения

Пример простого выражения lambda:

// 1. Не требует параметров, возвращаемое значение 5  
() -> 5  
  
// 2. Получение одного параметра (типа числа) и возвращение его удвоенной величины  
x -> 2 * x  
  
// 3. Получение двух параметров (чисел) и возвращение их разности  
(x, y) -> x – y  
  
// 4. Получение двух целых чисел и возвращение их суммы  
(int x, int y) -> x + y  
  
// 5. Принимает объект string и выводит его в консоль, не возвращая никакого значения (похоже, это return void)  
(String s) -> System.out.print(s)

В файле Java8Tester.java введите следующий код:

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("w3codebox");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

Исполнение вышеуказанного скрипта выводит результат:

$ javac Java8Tester.java 
$ java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Привет w3codebox
Привет Google

При использовании выражений lambda необходимо учитывать следующие два момента:

  • Выражения lambda主要用于 определение методов, выполняемых inline, например, простых метод-интерфейсов. В данном примере мы используем различные типы выражений lambda для определения методов интерфейса MathOperation. Затем мы определяем выполнение sayMessage.

  • Выражения lambda избегают необходимости использования анонимных методов и предоставляют Java простую, но мощную функциональную программирование.

Область переменных

Выражения lambda могут ссылаться только на локальные переменные, помеченные как final, что означает, что их нельзя изменять внутри lambda, в противном случае возникнет ошибка компиляции.

В файле Java8Tester.java введите следующий код:

public class Java8Tester {
 
   final static String salutation = "Hello! ";
   
   public static void main(String args[]){
      GreetingService greetService1 = message -> 
      System.out.println(salutation + message);
      greetService1.sayMessage("w3codebox");
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
}

Исполнение вышеуказанного скрипта выводит результат:

$ javac Java8Tester.java 
$ java Java8Tester
Привет! w3codebox

Мы также можем напрямую обращаться к локальным переменным внешнего выражения lambda:

public class Java8Tester {
    public static void main(String args[]) {
        final int num = 1;
        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
        s.convert(2); // результат вывода - 3
    }
 
    public interface Converter<T1, T2> {
        void convert(int i);
    }
}

Локальные переменные выражений lambda могут не объявляться как final, но они должны быть не изменяемыми после них (именно это и означает隐性 final)

int num = 1;  
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;  
// информация об ошибке: локальная переменная num определена в окружающем масштабе должна быть final или эффективно 
 final

В Lambda-выражениях не разрешается声明 параметр с именем, которое совпадает с именем локальной переменной или параметра.

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); // компиляция выйдет ошибку

Java 8 новые возможности