Давайте возьмем случай, когда переменная используется Lambda.
Возьмем класс (Doge), использующий функциональный интерфейс (PrintCoin), который печатает количество монет.
Функциональный интерфейс выглядит следующим образом: он использует один абстрактный метод print().
@FunctionalInterface interface PrintCoin{ void print(); }
Класс Doge выглядит так, мы определяем функцию как
() -> System.out.println('Вот ваш doge = '+coin);
который сопоставляется с print()
class Doge{ int coin; public void getDoge(){ PrintCoin printCoin = () -> System.out.println("Here's your doge = "+coin); printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); } }
Вывод будет выглядеть так
Here's your doge = 0
Супер просто! Лямбда просто потребляет значение экземпляра.
Значение монеты по умолчанию равно 0. Давайте инициализируем значения.
Вуаля! Отсюда становится очень легко!
Переменная экземпляра, инициализированная в методе
В предыдущем примере монета была инициализирована значением по умолчанию. Давайте инициализируем значение внутри метода.
@FunctionalInterface interface PrintCoin{ void print(); } class Doge{ int coin; public void getDoge(){ coin = 100; //init inside method PrintCoin printCoin = () -> System.out.println("Here's your doge = "+coin); printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); } }
Вывод,
Here's your doge = 100
Мы видим, что лямбда может получить обновленное значение переменной экземпляра в своей функции.
Переменная экземпляра, инициализированная внутри Lambda
Давайте напрямую инициализируем значение монеты внутри Lambda.
Можем ли мы манипулировать значением после инициализации? ДА ДА!
@FunctionalInterface interface PrintCoin{ void print(); } class Doge{ int coin; public void getDoge(){ PrintCoin printCoin = () -> { coin = 50; //init inside lambda coin = coin + 50; //manipulating value inside lambda System.out.println("Here's your doge = "+coin); }; printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); //checking the value after manipulation outside lambda System.out.println("Doge value ="+ doge.coin); } }
Вывод? ты знаешь это!
Here's your doge = 100 Doge value =100
Таким образом, мы можем манипулировать и инициализировать значения внутри лямбды.
Ссылочные переменные и лямбда
Мы добавим список целых чисел, определяющих купленные монеты.
Затем мы добавим общее количество купленных монет.
@FunctionalInterface interface PrintCoin{ void print(); } class Doge{ int coin; List<Integer> coinBought = Arrays.asList(80,20); //reference public void getDoge(){ PrintCoin printCoin = () -> { coin = 50; coin += coinBought.stream().reduce(0, (coin1,coin2) -> coin1+coin2); //summation of list System.out.println("Doge to the MOoon! Bag it sis = "+coin); }; printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); System.out.println("Doge value = "+ doge.coin); } }
Вывод выглядит так,
Doge to the MOoon! Bag it sis = 150 Doge value =150
Как мы видим, мы получили доступ к ссылкам внутри лямбды.
Идеально!
Давайте попробуем инициализировать ссылку внутри лямбда
package com.company; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @FunctionalInterface interface PrintCoin{ void print(); } class Doge{ int coin; List<Integer> coinBought; public void getDoge(){ PrintCoin printCoin = () -> { coin = 50; coinBought = new ArrayList(); //init reference inside lambda still remains local to lambda coinBought.add(80); coinBought.add(20); coin += coinBought.stream().reduce(0, (coin1,coin2) -> coin1+coin2); System.out.println("Doge to the MOoon! Bag it sis = "+coin); }; printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); System.out.println("Doge value = "+ doge.coin); } }
Ссылка была инициализирована локально для лямбда-функции.
Если мы попытаемся получить к нему доступ в другом месте, он выдаст ошибку, как показано ниже.
package com.company; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @FunctionalInterface interface PrintCoin{ void print(); } class Doge{ int coin; List<Integer> coinBought; public void getDoge(){ PrintCoin printCoin = () -> { coin = 50; coinBought = new ArrayList(); //init is local to lambda function coinBought.add(80); coinBought.add(20); coin += coinBought.stream().reduce(0, (coin1,coin2) -> coin1+coin2); System.out.println("Doge to the MOoon! Bag it sis = "+coin); }; coinBought.add(30); //ERROR printCoin.print(); } public static void main(String []args){ Doge doge = new Doge(); doge.getDoge(); System.out.println("Doge value = "+ doge.coin); } }
Вывод,
Exception in thread "main" java.lang.NullPointerException at com.company.Doge.getDoge(Main.java:28) at com.company.Doge.main(Main.java:34)
Почему это происходит? потому что выполненная инициализация является локальной для метода.
В заключении,
Переменные Insatnce можно инициализировать/манипулировать в любом месте внутри метода
Переменные экземпляра можно инициализировать/манипулировать внутри любых лямбда-функций
Это все люди!
Играйте больше! Дайте мне знать, если я пропустил какие-либо сценарии.
Ваше здоровье!