Передача лямбда-выражений в качестве аргументов в Java

Передача лямбда-выражений в качестве аргументов в Java

Как известно, лямбда-выражение может быть использовано в любом контексте, предоставляющем его целевой тип

Один из таких контекстов возни­кает при передаче лямбда-выражения в качестве аргумента.

В действительностипередача лямбда-выражений в качестве аргументов является весьма распростра­ненным примером их применения.

Более того, это весьма эффективное их при­менение, поскольку оно дает возможность передать исполняемый код методу в качестве его аргумента.

Благадоря этому значительно повышается выразительная сила Java.

Для передачи лямбда-выражения в качестве аргумента параметр, получающий это выражение в качестве аргумента, должен иметь тип функционального интерфейса, совместимого с этим лямбда-выражением.

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

В следующем примере программы демонстрируется весь этот процесс:

//  -    

interface StringFunc {
    String func(String n);
}

class LambdaAsArgumentsDemo {

    //       
    // . ,     
    //    ,  ,
    //   -.   
    //    .

    static String stringOp(StringFunc sf, String s) {
    return sf.func(s);
    }

    public static void main(String args[]) {

    String inStr = "-   Java";
    String outStr;

    System.out.println("  : " + inStr);

    //    -, 
    //        ,
    //   stringOp()

    outStr = stringOp((str) -> str.toUpperCase(), inStr);
    System.out.println("    : " + outStr);

    //     -, 
    //     

    outStr = stringOp((str) -> {
                String result = "";
                int i;

                for(i = 0; i < str.length(); i++) {
                    if(str.charAt(i) != ' ') {
                    result += str.charAt(i);
                    }
                }

                return result;
               }, inStr);

    System.out.println("    : " + outStr);

    // ,      StringFunc,
    //    -. , 
    //    reverse   
    //  StringFunc

    StringFunc reverse = (str) -> {
                String result = "";
                int i;

                for(i = str.length() - 1; i >= 0; i--) {
                    result += str.charAt(i);
                }

                return result;
                  };

    //    reverse     
    //   stringOp()
    //      StringFunc

    System.out.println("  : " + stringOp(reverse, inStr));

    }
}

Ниже приведен результат выполнения данной программы:

pro-java.ru@admin:~$ javac lambdarg.java
pro-java.ru@admin:~$ java LambdaAsArgumentsDemo
  : -   Java
    : -   JAVA
    : -Java
  : avaJ   -
pro-java.ru@admin:~$

Прежде всего обратите внимание в данном примере программы на метод stringOp(), у которого имеются два параметра.

Первый параметр относитсяк типу StringFunc, т.е. к функциональному интерфейсу. Следовательно, этот параметр может получать ссылку на любой экземпляр функционального интерфейса StringFunc, в том числе и создаваемый в лямбда-выражении.

А второй параметр метода, stringOp(), относится к типу String и обозначает обрабатываемую сим­вольную строку.

Затем обратите внимание на первый вызов метода stringOp():

outStr = stringOp((str) -> str.toUpperCase(), inStr);

где в качестве аргумента данному методу передается простое лямбда-выражение. При этом создается экземпляр функционального интерфейса StringFunc и ссыл­ка на данный объект передается первому параметру метода stringOp().

Таким образом, код лямбда-выражения, встраиваемый в экземпляр класса, передается данному методу. Контекст целевого типа лямбда-выражения определяется типом его параметра.

А поскольку лямбда-выражение совместимо с этим типом, то рас­сматриваемый здесь вызов достоверен.

Встраивать в метод такие простые лямбда­в-ыражения, как упомянутое выше, нередко оказывается очень удобно, особенно когда лямбда-выражение предназначается для однократного употребления.

Далее в рассматриваемом здесь примере программы методу stringOp() пере­дается блочное лямбда-выражение.

Оно удаляет пробелы из исходной символьной строки и еще раз показано ниже.

outStr = stringOp((str) -> {
                String result = "";
                int i;

                for(i = 0; i < str.length(); i++) {
                    if(str.charAt(i) != ' ') {
                    result += str.charAt(i);
                    }
                }

                return result;
               }, inStr);

И хотя здесь указывается блочное лямбда-выражение, описанный выше про­цесс передачи лямбда-выражения остается тем же самым и для простого одиноч­ного лямбда-выражения.

Но в данном случае некоторым программистам синтак­сис может показаться несколько неуклюжим.

Если блочное выражение кажется слишком длинным для встраивания в вызов метода, то его можно просто присвоить переменной ссылки на функциональный интерфейс, как это делалось в предыдущих примерах.

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

Это лямбда-вы­ражение присваивается переменной reverse, ссылающейся на функциональны йинтерфейс StringFunc.

Следовательно, переменную reverse можно передатьв качестве аргумента первому параметру метода stringOp().

Именно так и делает­ся в конце данной программы, где методу stringOp() передаются переменная reverse и обрабатываемая символьная строка.

Экземпляр, получаемый в результате вычисления каждого лямбда-выражения, является реализацией функционального интерфейса StringFunc, поэтому каждое из этих выражений может быть передано в качестве первого аргумента вызываемому методу stringOp().

И последнее замечание: помимо инициализации переменных, присваиванияи передачи аргументов, следующие операции образуют контекст целевого типа лямбда-выражений: приведение типов, тернарная операция ?, инициализация массивов, операторы return, а также сами лямбда-выражения.

Интересное видео по теме для нашей аудитории

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *