java 8. lambdas
TRANSCRIPT
Синтаксис lambda-выражений
▪ (String s) -> { return s. length();}
▪ (s) -> { return s. length();}
▪ (s) -> s. length()
▪ s -> s. length()
▪ () -> System.gc();
( Lambda Parameters ) -> { Lambda Body }
Пример:
▪ (int x, int y) -> x+y
▪ (x, y) -> x+y
▪ (int... x) -> x[0]+1
▪ (int[] x) -> x[0]+1
But illegal:
▪ (x, int y) -> x+y
▪ (x, final y) -> x+y
Функциональные интерфейсы
▪ Интерфейс с единственным абстрактным методом
▪ Аннотация @FunctionalInterface не обязательна
Примеры стандартных функциональных интерфейсов
Функциональныйинтерфейс
Типы параметров Возвращаемый тип Имя абстрактногометода
Runnable Отсутствует Void run
Supplier<T> Отсутствует T get
Consumer<T> T Void accept
BiConsumer<T, U> T, U Void accept
Function<T, R> T R apply
BiFunction<T,U, R> T, U R apply
UnaryOperator<T> T T apply
BinaryOperator<T> T, T T apply
Predicate<T> T Boolean test
BiPredicate<T,U> T,U Boolean test
Примеры стандартных функциональных интерфейсовдля примитивов
Функциональныйинтерфейс
Типы параметров Возвращаемый тип Имя абстрактногометода
LongFunction<T> long T apply
LongToIntFunction long int apply
ToLongFunction<T> T long apply
Ссылки на методы
▪ объект :: метод экземпляра
▪ класс :: статический метод
▪ класс :: метод экземпляра
В том числе:
▪ this :: метод экземпляра
▪ super :: метод экземпляра
▪ класс:: new
Область действия переменных
▪ Кодовый блок
▪ Параметры
Lambda выражение категории noncapturing :
▪ Кодовый блок
▪ Параметры
▪ Значение свободных переменных
Lambda выражение категории capturing :
Область действия переменных
Legal: x и y являются effectively final
void m1(int x) {int y = 1;foo(() -> x+y);
}
Legal: x и y являются effectively final
void m2(int x) {int y;y = 1;foo(() -> x+y);
}
Illegal: y являются effectively final, но гарантированоне инициализирована.
void m3(int x) {int y;if (...) y = 1;foo(() -> x+y);
}
Legal: x и y являются effectively final
void m4(int x) {int y;if (...) y = 1; else y = 2;foo(() ->; x+y);
}
Область действия переменных
Illegal : x не являются effectively final
void m5(int x) {int y;if (...) y = 1;y = 2;foo(() -> x+y);
}
Illegal: x не являются effectively final
void m6(int x) {foo(() -> x+1);x++;
}
Illegal : x не являются effectively final
void m7(int x) {foo(() -> x=1);
}
Illegal : y не являются effectively final
void m8() {int y;foo(() -> y=1);
}
Invokedynamic
Первый вызов: Последующие вызовы:
invokedynamic
BootStrap метод
CallSite
MethodHandlepublic Object foo(..){…}
вызывает
возвращает
Указывающий на
invokedynamic
CallSite
MethodHandlepublic Object foo(..){…}
Извлекае MH из
Указывающий на
или сразувызывает
метод напрямую
Invokedynamic
Пример:
Printer p = System.out::println;p.print("Str");
MethodHandleХранит указатель на метод
CallSiteОбъект,
описывающий«место» вызова в
коде
Трансляция lambda выражений
Стратегия 1. Lambda выражение категории noncapturing :
Исходный код:
class A {public void foo() {List<String> list = ...list.forEach( s -> {
System.out.println(s); } );
}}
Оттранслированый код:
class A {public void foo() {
List<String> list = ...list.forEach(indy((MH(metaFactory),
MH(invokeVirtual Consumer. accepts),MH(invokeStatic A.lambda$1)( )));
}private static void lambda$1(String s) {
System.out.println(s);}
}
Трансляция lambda выражений
Стратегия 2. Lambda выражение категории capturing :
Исходный код:
class B {public void foo() {
List<String> list = ...final int bottom = ..., top = ...;list.removeIf( s ->
(s. length() >= bottom &&s. length() <= top) );
}}
Оттранслированый код:
class B {public void foo() {
List<String> list = ...final int bottom = ..., top = ...;list.removeIf(indy((MH(metaFactory), MH(invokeVirtual Predicate.apply),MH(invokeStatic B.lambda$1))( bottom, top )))); }
static boolean lambda$1(int bottom, int top, String s) {return (p. length() >= bottom && p. length() <= top;
}}
Трансляция lambda выражений
Стратегия 3. Lambda выражение категории capturing :
Исходный код:
class B {final int bottom = ..., top = ...;
public void foo() {List<String> list = ...list.removeIf( s ->
(s. length() >= bottom &&s. length() <= top) );
}}
Оттранслированый код:
class B {final int bottom = ..., top = ...;public void foo() {
List<String> list = ...list.forEach(INDY((MH(metaFactory), MH(invokeVirtual Predicate.apply),MH(invokeVirtual B.lambda$1))( this )))); }
private boolean lambda$1(Element e) {return e.getSize() < minSize;
}}
Трансляция lambda выражений
Стратегия 4. Ссылка на метод :
Исходный код:
class A {public void foo() {List<String> list = ...list.filter(String::isEmpty) }
}
Оттранслированый код:
class A {public void foo() {
List<String> list = ...list.filter(
indy(MH(metaFactory), MH(invokeVirtual Predicate.apply),MH(invokeVirtual String.isEmpty))()))
}}
Трансляция lambda выражений
Стратегия 5. Аргументы переменной длины:
Исходный код:
interface IIS {void foo(Integer a1, Integer a2, String a3);
}class Foo {
static void m(Number a1, Object... rest) { ... }}class Bar {
void bar() {IIS x = Foo::m;
}}
Оттранслированый код:
class Bar {void bar() {
SIS x = indy((MH(metafactory), MH(invokeVirtual IIS.foo),MH(invokeStatic m$bridge))( ))
}
static private void m$bridge(Integer a1, Integer a2, String a3) {
Foo.m(a1, a2, a3);}
}
Использованные источники
▪ Кей С. Хорстманн – Java SE 8. Вводный курс
▪ JLS - Lambda Expressions [http://docs.oracle.com/javase/specs/jls/se8/html/ ]
▪ Translation of Lambda Expressions [http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html ]
▪ State of the Lambda [http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html]
▪ Д. Сосноски - Изменения в языке Java 8[http://www.ibm.com/developerworks/ru/library/j-java8lambdas/]