Лямбда-выражения в Java8
import java.util.concurrent.Callable;
public class AdvancedLambda {
static void invoke(Runnable r){
r.run();
}
static Object invoke(Callable c) throws Exception {
return c.call();
}
public static void main(String[] args) throws Exception {
String s = (String) invoke(() -> true);
System.out.println(s);
}
}
может ли кто-нибудь помочь мне понять это? У меня сложилось впечатление, что мы можем использовать выражения lamba в Java 8 только тогда, когда реализуем интерфейс и переопределяем его методы (заменяя анонимные классы лямбда-выражениями).
и в какой ситуации будет метод invoke(Runnable r)
назвать?
5 ответов
в следующей строке
String s = (String) invoke(() -> true);
это на самом деле invoke(Callable)
что называется. Причина:
-
() -> true
- лямбда-выражение, которое имеет нулевой формальный параметр и возвращает результат. - такая подпись (нулевой параметр, одиночный результат) совместима с функциональным методом
call()
наCallable
интерфейс. Обратите внимание, что интерфейс не нужен@FunctionalInterface
аннотации, он просто должен иметь один абстрактный метод.
если вы хотите вызвать invoke(Runnable)
вместо этого вам нужно будет создать лямбду, совместимую с функциональным методом, который принимает нулевой параметр и не возвращает результата (т. е. соответствует сигнатуре run()
). Что-то вроде этого:--11-->
invoke(() -> System.out.println("foo"));
которая просто выводит foo
когда побежал.
лямбда-выражение обеспечивает реализацию функционального интерфейса. Это то, что делает фрагмент кода.
вызов invoke
передает лямбда-выражение без аргументов, которое возвращает значение (a boolean
в вашем случае). Поэтому он соответствует Object invoke(Callable c)
, а не void invoke(Runnable r)
(поскольку Callable
' s call
метод имеет возвращаемое значение, а Runnable
' s run
метод ничего не возвращает).
invoke(() -> {System.out.println("something");});
будем называть void invoke(Runnable r)
, так как в этом случае лямбда-выражение не имеет возвращаемого типа.
только когда мы реализуем интерфейс и переопределить его методы
это, более или менее, то, что вы здесь делаете. Не методs, но только один способ: call()
. Это () -> true
- Это ваша реализация Callable#call()
.
другими словами, эта строка:
String s = (String) invoke(() -> true);
было бы полностью эквивалентно этому:
String s = (String) invoke(new Callable() {
@Override
public Object call() throws Exception {
return true;
}
});
взгляните на пример ниже.
import javafx.beans.DefaultProperty;
import jdk.nashorn.internal.codegen.CompilerConstants;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by KUMAJYE on 13/09/2016.
*/
public class ThreadMonitor {
private static int noOfThreads = 0;
public static void main(String[] args) {
ThreadModel threadModel;
noOfThreads = Integer.parseInt(args[0]);
if (noOfThreads > 0) {
threadModel = getThreadingModelForCallsInCallingThread();
} else {
threadModel = getAsynchThreadingModel();
}
}
public static ThreadModel getThreadingModelForCallsInCallingThread() {
ExecutorService executor = Executors.newFixedThreadPool(noOfThreads);
return (r) -> executor.submit(r);
}
public static ThreadModel getAsynchThreadingModel() {
// do execution on same Thread or separate Thread.
// or
// r.run();
return (r) -> new Thread(r).start();
}
interface ThreadModel {
void invoke(Runnable r);
}
}
- лямда -: может использоваться только для выполнения фоновых задач (здесь компилятор затем выясняет)
- выражения: возвращают какое-то значение
лямбда-выражение-это еще один способ написания экземпляра анонимного класса, чтобы упростить запись экземпляра анонимного класса. В JVM он не будет занимать много памяти по сравнению с обычным созданием объектов java с new
(выполнении статических переменных, статические блоки, загрузка классов из всей иерархии ).
лямбда-выражения синтаксис:
(params) -> expression to implement a @FunctionalInterface
в вашем тесте: String s = (String) invoke(() -> true);
выражение имеет тип возвращаемого true
не аргумент. Так что Runnable
FunctionalInterface
не соответствует лямбда-выражению, потому что оно имеет . Он совпадает с Callable
FuncationalInterface
используяV call()
.
как работают лямбда-выражения под капотом?
Может показаться, что лямбда-выражения-это просто синтаксический сахар для анонимных внутренних классов, но есть гораздо более элегантный подход. Самое простое объяснение: лямбда-выражение представлено новым методом и вызывается во время выполнения с помощью invokedynamic.
Исходный Код:
class LambdaExample {
public void abc() {
Runnable r = () -> {
System.out.println("hello");
}
r.run();
}
}
байт-кода эквивалентны:
class LambdaExample {
public void abc() {
Runnable r = <lambda as Runnable instance>;
r.run();
}
static void lambda() {
System.out.println("hello");
}
}
внутри JVM есть лямбда-фабрика это создает экземпляр функционального интерфейса (например, Runnable) из сгенерированного метода lambda (например, lambda$1).
лямбда-выражения великолепны, и в Java 8...