У меня возникли вопросы о лямбда-выражениях и RxJava. Эти вопросы в основном касаются не полного понимания лямбда-выражений или RxJava. Я попытаюсь объяснить лямбда-выражения как можно проще. RxJava я опишу отдельно.

Лямбда-выражения и RxJava

Что такое лямбда-выражения? Лямбда-выражения – это «всего лишь» новый способ сделать то же самое, что мы всегда могли сделать, но в более чистом и менее многословном новом способе использования анонимных внутренних классов.

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

Например:

 

1
2
3
4
5
6
7
8
9
abstract class Animal {
   abstract void speak();
}

Animal a = new Animal() {
   void speak() {
       System.out.println("Woff");
   }
};

 

В Android мы обычно используем анонимный внутренний класс в качестве слушателя, например, для кнопок такого рода:

 

1
2
3
4
5
6
7
8
9
Button btn = findViewById(R.id.button);
btn.setOnClickListener(
       new View.OnClickListener() {
           @Override
           public void onClick(final View view) {
               // Do some fancy stuff with the view parameter.
           }
       }
);

 

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

 

1
2
3
4
5
6
new View.OnClickListener() {
   @Override
   public void onClick(final View view) {
       // Do some fancy stuff with the view parameter.
   }
}

 

Лямбда-выражения могут использоваться только в том случае, если вам нужно переопределить не более одного метода. К счастью для нас, View.OnClickListener содержит только один. Посмотрите на код ниже. Как думаете, какую его часть нам придётся убрать?

 

1
2
3
4
5
6
new View.OnClickListener() {
   @Override
   public void onClick(final View view) {
       // Do some fancy stuff with the view parameter.
   }
}

 

После удаления практически всего кода, нам нужно добавить ->, как в приведенном ниже коде. Входящий параметр view может использоваться внутри функции так же, как и раньше.

 

1
2
3
(view) -> {
   // Do some fancy stuff with the view parameter.
}

 

В некоторых случаях вам может потребоваться добавить тип к параметру, если компилятору не удается его угадать, вы можете сделать это, добавив его перед параметром:

 

1
2
3
(View view) -> {
   // Do some fancy stuff with the view parameter.
}

 

Вы также можете использовать многострочный код:

 

1
2
3
4
5
(view) -> {
   Intent intent = new Intent(context, AuthActivity.class);
   intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |     Intent.FLAG_ACTIVITY_CLEAR_TASK);
   view.getContext().startActivity(intent);
} 

 

Если у вас есть интерфейс с методом, принимающим два параметра…

 

1
2
3
interface MyInterface {
   abstract void onMethod(int a, int b);
} 

 

…лямбда-выражение будет выглядеть следующим образом:

 

1
2
3
(a, b) -> {
   // Do some fancy stuff with the a and b parameter.
}

 

Если метод имеет возвращаемый тип…

 

1
2
3
interface MySecondInterface {
   abstract int onSecondMethod(int a, int b);
}

 

…лямбда-выражение будет выглядеть следующим образом:

 

1
2
3
(a, b) -> {
   return a + b;
}

 

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

 

1
(a, b) -> return a + b

 

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

 

1
(a, b) -> a + b

 

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

 

1
2
3
4
(a, b) -> {
   a+=1;
   return a + b;
}

 

Так что же мы сделали? Мы взяли это:

 

1
2
3
4
5
6
new MySecondInterface() {
   @Override
   public int onSecondMethod(final int a, final int b) {
       return a + b;
   }
};

 

и превратили вот в это:

 

1
(a, b) -> a + b

 

Осталось только одна вещь, ссылки на методы. Допустим, у нас есть интерфейс, как и раньше, и метод, который этот интерфейс принимает как параметр:

 

1
2
3
4
5
6
public interface Callback {
   public void onEvent(int event);
}
public void myMethod(Callback callback){

}

 

Без лямбда-выражения это выглядело бы так:

 

1
2
3
4
5
6
myMethod(new Callback() {
   @Override
   public void onEvent(final int state) {
       System.out.println(state);
   }
});  

 

Добавив лямбда-выражение, как мы это делали раньше, получим следующее:

 

1
MyMethod(state -> System.out.println(state));

 

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

 

1
MyMethod(System.out::println);

 

Параметр будет передаваться автоматически, без необходимости использования другого кода! Удивительно, правда? Надеюсь, вы узнали что-то новое!

Перевод – [Оригинальная статья]

03/07/2018

0 комментариев к статье "Объяснение лямбда-выражений"

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