Java 中 lambda 的返回值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38540481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:24:29  来源:igfitidea点击:

Return value by lambda in Java

javalambdarunnable

提问by Freeman

Till now I manage to find all answers I need but this one confusing me. Let's say we have example code:

直到现在我设法找到我需要的所有答案,但这个让我感到困惑。假设我们有示例代码:

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 Study Guide (Exam 1Z0-808) book says that these two lines are equivalent:

OCA Study Guide (Exam 1Z0-808) book 说这两行是等价的:

a -> a.canHop()
(Animal a) -> { return a.canHop(); }

Does this mean that, behind the scenes, Java adds keyword returnto code in the first case?

这是否意味着,在幕后,Java在第一种情况下为代码添加了关键字return

If answer is YES then how next code compile (imagine everything else is in proper place):

如果答案是肯定的,那么接下来的代码是如何编译的(想象其他一切都在适当的位置):

static int counter = 0;
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> counter++));

if we know that signatures for executeand Runnable's runare:

如果我们知道execute和 Runnable 的运行签名是:

void execute(Runnable command)
void run()

If answer is NO then how Java know when it need to return something and when not to? Maybe in

如果答案是否定的,那么 Java 怎么知道什么时候需要返回一些东西,什么时候不需要呢?也许在

a -> a.canHop()

case we wanted to ignore booleanreturn type of method.

如果我们想忽略方法的布尔返回类型。

采纳答案by Peter Lawrey

Does this mean that, behind the scenes, Java adds keyword return to code in the first case?

这是否意味着,在幕后,Java 在第一种情况下为代码添加了关键字 return?

No, The compiler generates byte code, and it might generate the same byte code but it doesn't change the syntax and then compile it again.

不,编译器生成字节码,它可能会生成相同的字节码,但不会更改语法,然后再次编译。

we wanted to ignore boolean return type of method.

我们想忽略布尔返回类型的方法。

It has the option of ignoring a value based on what functional interfaces it is considering.

它可以根据正在考虑的功能接口忽略某个值。

a -> a.canHop()

could be

可能

(Animal a) -> { return a.canHop(); }

or

或者

(Animal a) -> { a.canHop(); }

based on context, however it favours the first if possible.

基于上下文,但是如果可能的话,它倾向于第一个。

Consider ExecutorService.submit(Callable<T>)and ExecutorService.submit(Runnable)

考虑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?

Saving the return type you can see it's a Callable<Integer>

保存返回类型你可以看到它是一个 Callable<Integer>

final Future<Integer> submit = es.submit(() -> counter++);


To try yourself, here is a longer example.

为了自己尝试,这里有一个更长的例子。

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();
}

prints

印刷

null
2
counter: 3
null

The first submittake a Runnableso Future.get()returns null

第一个submit取一个Runnable所以Future.get()返回null

The second submitdefaults to being a Callableso Future.get()returns 2

第二个submit默认为CallablesoFuture.get()返回2

The third submitcan only be a voidreturn value so it must be a Runnableso Future.get()returns null

第三个submit只能是一个void返回值所以它必须是一个Runnable所以Future.get()返回null

回答by SamTebbs33

You are confused about the scope of the returnstatement. The returnstatement (whether inserted as bytecode by the compiler or as source code by the programmer) returns from the lambda, and not from the method that calls the lambda.

您对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");
}

回答by Guillaume Poussel

Yes, when specifying only a single statement, its value is automatically returned from the lambda.

是的,当只指定一个语句时,它的值会自动从 lambda 返回。

Then, since Runnableis a Functional Interface, it can be defined as a lambda. The return type is void, so any return value inside the lambda will be ignored.

然后,由于Runnable是函数式接口,因此可以将其定义为 lambda。返回类型是void,因此 lambda 内的任何返回值都将被忽略。