Java. Доступ к элементам класса из лямбда-выражения. Захват переменных в лямбда-выражениях. Пример

Доступ к элементам класса из лямбда-выражения. Захват переменных в лямбда-выражениях. Пример


Содержание


Поиск на других ресурсах:




1. Доступ к элементам класса из лямбда-выражения. К каким элементам класса можно получить доступ из лямбда-выражения?

Если в классе объявлен метод, содержащий лямбда-выражение, то из этого лямбда-выражения можно получить доступ к следующим элементам класса:

  • полям данных (членам данных) класса. Это касается как членов данных экземпляра класса, так и статических членов данных;
  • методов класса. Это касается как методов экземпляра, так и статических методов;
  • переменных (экземпляров), объявленных непосредственно в теле лямбда-выражения;
  • переменных (экземпляров), объявленных в обьемлющих фигурных скобках { }, в которых размещается программный код лямбда-выражения. В этом случае переменная (экземпляр) считается захваченной.

 

2. Доступ к полям и методам класса из лямбда-выражения. Пример

В примере осуществляется доступ к полям a, b из лямбда-выражения, размещенного в классе LambaFunction.

// Функциональный интерфейс
interface IFunction {
  void Function();
}

// Класс, содержащий метод с лямбда-выражением
class LambdaFunction {
  int a; // поле данных класса
  static int b; // статическое поле

  // метод класса
  void PrintA() {
    System.out.println("a = " + a);
  }

  // статический метод класса
  static void PrintB() {
    System.out.println("b = " + b);
  }

  // Метод с лямбда-выражением
  void MethodLambda() {
    // 1. Лямбда-выражение
    IFunction ref = () -> {
      // Есть доступ ко всем этим элементам
      a = 8;
      LambdaFunction.b = 15;
      PrintA();
      LambdaFunction.PrintB();
    };

    // 2. Вызвать метод Function интерфейса IFunction
    ref.Function();
  }
}

public class Lambda {

  public static void main(String[] args) {
    // Клиентский код - вызов метода MethodLambda()
    LambdaFunction lf = new LambdaFunction();
    lf.MethodLambda();
  }
}

Результат выполнения программы

a = 8
b = 15

В вышеприведенном примере объявляется класс LambdaFunction. В этом классе реализован метод MethodLambda(), который содержит код лямбда-выражения. Из этого лямбда-выражения доступны следующие элементы:

  • внутреннее поле a;
  • статическое поле b;
  • метод экземляра класса PrintA();
  • статический метод PrintB().

 

3. Объявление переменных (экземпляров) в теле лямбда-выражения. Пример

В теле лямбда-выражения можно объявлять любые переменные или экземпляры классов. Допускается объявление переменных с модификатором final. Запрещается объявлять статические (static) переменные (экземпляры).

Пример. В фрагменте ниже в теле лямбда-выражения объявляется и используется переменная z целого типа.

...

// лямбда-выражение

ref = () -> {
  int z; // объявление переменной в теле лямбда-выражения

  // ...

  // использование переменной z
  z = 277;

  // ...
};

 

4. Захват переменных в лямбда-выражениях. Завершенные (final) переменные. Особенности

При использовании лямбда-выражений можно доступиться к переменным из объемлющей области действия, которая определяется фигурными скобками { }.

В этом случае переменная, к которой осуществляется доступ, считается захваченной. Захват переменной — это использование в лямбда-выражении переменной, которая объявлена в объемлющей области действия.

Чтобы из лямбда-выражения можно было захватить переменную, эта переменная должна быть завершенной. Термин «завершенная» означает, что переменная должна быть объявлена с модификатором доступа final, например, так

final int value; // объявляется завершенная переменная value

Завершенную переменную можно использовать в теле лямбда-выражения. Однако, запрещено изменять эту переменную. При попытке изменить значение завершенной (final) переменной компилятор будет выдавать ошибку.

 

5. Пример, демонстрирующий использование завершенной переменной

В нижеследующем коде демонстрируется использование завершенной переменной x в теле лямбда-выражения.

// Функциональный интерфейс
interface IFunction {
  void Function();
}

// Класс, содержащий метод с лямбда-выражением
class LambdaFunction {

  // Метод с лямбда-выражением
  void MethodLambda() {
    // 1. До лямбда-выражения
    final int x = 33; // переменная в методе, которая будет захвачена в лямбда-выражении
    int y = 55; // переменная, которая не будет захвачена в лямбда-выражении

    // 2. Лямбда-выражение
    IFunction ref = () -> {
      // нельзя изменить переменную x, потому что она объявлена как final
      // x = 77; - ошибка на этапе компиляции

      // однако, ее можно использовать
      int z;
      z = x + 5; // теперь переменная x захвачена

      // Вывести z
      System.out.println("z = " + z); // z = 38
    };

    // Вызвать метод Function интерфейса IFunction
    ref.Function();

    // 3. После лямбда-выражения
    // переменная x уже захвачена (final), поэтому невозможно ее изменить
    // x = 44;

    // переменную x можно только читать (использовать)
    System.out.println("x = " + x);

    // переменная y не захвачена
    y = 88; // поэтому ее можно изменять
    System.out.println("y = " + y);
  }
}

public class Lambda {

  public static void main(String[] args) {
    // Доступ к полям и методам класса из лямбда-выражения
    LambdaFunction lf = new LambdaFunction();
    lf.MethodLambda();
  }
}

 


Связанные темы