在 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 Study Guide (Exam 1Z0-808) 书说这两行是等价的:

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

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

如果答案是肯定的,那么下一个代码将如何编译(想象其他一切都在适当的地方):

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

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

 void execute(Runnable command)
void run()

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

a -> a.canHop()

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

原文由 Freeman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 873
2 个回答

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

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

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

它可以选择忽略基于它正在考虑的功能接口的值。

 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

The third submit can only be a void return value so it must be a Runnable so Future.get() returns null

原文由 Peter Lawrey 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

原文由 Guillaume Poussel 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题