Java中lambda的返回值
到目前为止,我设法找到了我需要的所有答案,但是这个答案令我困惑。比方说,我们有示例代码:Java中lambda的返回值
public class Animal {
private String species;
private boolean canHop;
private boolean canSwim;
public Animal(String speciesName, boolean hopper, boolean swimmer) {
species = speciesName;
canHop = hopper;
canSwim = swimmer;
}
public boolean canHop() { return canHop; }
public boolean canSwim() { return canSwim; }
public String toString() { return species; }
}
public interface CheckAnimal {
public boolean test(Animal a);
}
public class FindSameAnimals {
private static void print(Animal animal, CheckAnimal trait) {
if(trait.test(animal)){
System.out.println(animal);
}
public static void main(String[] args) {
print(new Animal("fish", false, true), a -> a.canHop());
}
}
OCA学习指南(考试1Z0-808)一书说,这两条线是相同的:
a -> a.canHop()
(Animal a) -> { return a.canHop(); }
这是否意味着,在幕后,Java的增加关键字返回代码在第一种情况下?
如果答案为是,则代码的下一个编译(想象一下,其他的一切都是在正确的地方):
static int counter = 0;
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> counter++));
如果我们知道,签名执行和Runnable接口的运行是:
void execute(Runnable command)
void run()
如果答案是否定的,那么Java如何知道它何时需要返回什么以及何时不需要返回?也许在
a -> a.canHop()
情况下,我们想忽略方法布尔返回类型。
这是否意味着,在幕后,Java的增加在第一种情况下的关键字返回代码?
不,编译器生成字节码,它可能会生成相同的字节码,但它不会更改语法,然后再次编译。
我们想忽略boolean返回类型的方法。
它可以根据它正在考虑的功能接口忽略一个值。
a -> a.canHop()
可能是
(Animal a) -> { return a.canHop(); }
或
(Animal a) -> { a.canHop(); }
根据上下文,但它有利于第一,如果可能的。
考虑ExecutorService.submit(Callable<T>)
和ExecutorService.submit(Runnable)
ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(() -> counter++); // has to be Runnable
es.submit(() -> counter++); // Callable<Integer> or Runnable?
保存返回类型,你可以看到它是一个Callable<Integer>
final Future<Integer> submit = es.submit(() -> counter++);
尝试自己,这里是一个较长的例子。
static int counter = 0;
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newSingleThreadExecutor();
// execute only takes Runnable
es.execute(() -> counter++);
// force the lambda to be Runnable
final Future<?> submit = es.submit((Runnable)() -> counter++);
System.out.println(submit.get());
// returns a value so it's a Callable<Integer>
final Future<Integer> submit2 = es.submit(() -> counter++);
System.out.println(submit2.get());
// returns nothing so it must be Runnable
final Future<?> submit3 = es.submit(() -> System.out.println("counter: " + counter));
System.out.println(submit3.get());
es.shutdown();
}
打印
null
2
counter: 3
null
第一submit
采取Runnable
所以Future.get()
返回null
第二submit
默认为是一个Callable
所以Future.get()
返回2
的第三submit
只能是一个void
返回值,所以它必须是一个Runnable
所以Future.get()
回报null
而且只在执行时需要Runnable:es.execute (() - > counter ++);那么它会被视为副作用? – Freeman
@Freeman任何不返回值的方法只能有副作用。 –
您对return
声明的范围感到困惑。 return
语句(不管是由编译器作为字节码还是由程序员作为源代码插入)都从lambda返回,而不是从调用lambda的方法返回。
void foo() {
Supplier<String> s =() -> { return "bar" };
String s = s.get(); // s is assigned to "bar"
// Execution continues as the return statement in the lambda only returns from the lambda and not the enclosing method
System.out.println("This will print");
}
它知道它可以忽略Runnable情况下的返回类型,因为run()返回void。它知道它不能忽略CheckAnimal情况下的返回类型,因为test()不会返回void。 –
lambada做了一个方法应该做的事情,如果你的方法包含返回类型,那么lambda将提供其他方式,否则它是写方法的快捷方式,所以不要混淆你自己 – emotionlessbananas