Рефакторинг анонимных классов (которые реализуют один единственный метод) в лямбда-выражения делает ваш код более лаконичным и читабельным. Например, вот анонимный класс для Runnable
и его лямбда-эквивалент:
01
02
03
04
05
06
07
08
09
10
|
// using an anonymous class Runnable r = new Runnable() { @Override public void run() { System.out.println( "Hello" ); } }; // using a lambda expression Runnable r2 = () -> System.out.println( "Hello" ); |
Однако это не всегда так просто!
Вот несколько ошибок:
1. Различные правила определения объема
Существуют разные правила определения объема между анонимными классами и лямбда-выражениями. Например, в лямбда-выражениях this
и super
имеют лексическую область видимости, то есть они относятся к включающему классу, но в анонимном классе они относятся к самому анонимному классу. Точно так же локальные переменные, объявленные в лямбда-выражениях, будут конфликтовать с переменными, объявленными в классе включения, но в анонимных классах им разрешено скрывать переменные в классе включения. Вот пример:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
int foo = 1 ; Runnable r = new Runnable() { @Override public void run() { // this is ok! int foo = 2 ; } }; Runnable r2 = () -> { // compile error: Lambda expression's local variable foo cannot // redeclare another local variable defined in an enclosing scope. int foo = 2 ; }; |
2. Перегруженные методы
Если у вас перегруженный метод, использование лямбда-выражений может привести к неоднозначному вызову метода и потребует явного приведения. Вот пример:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
// Functional interface interface Task { public void execute(); } // Overloaded methods public static void go( final Runnable r) { r.run(); } public static void go( final Task t) { t.execute(); } // Calling the overloaded method: // When using an anonymous class, there is no ambiguity because // the type of the class is explicit at instantiation go( new Task() { @Override public void execute() { System.out.println( "Hello" ); } }); // When using a lambda expression, there is a compile error! // The method go(Runnable) is ambiguous go(() -> { System.out.println( "Hello" ); }); // This ambiguity can be solved with an explicit cast go((Task)() -> { System.out.println( "Hello" ); }); |
Ссылка: | Java 8: преобразование анонимных классов в лямбда-выражения от нашего партнера по JCG Фахда Шарифа в блоге fahd.blog . |