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();
  }
}

 


Зв’язані теми