java - 在 Java 中通过 lambda 返回值

标签 java lambda runnable

到目前为止,我设法找到了我需要的所有答案,但这个让我感到困惑。假设我们有示例代码:

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 的 run 的签名是:

void execute(Runnable command)
void run()

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

a -> a.canHop()

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

最佳答案

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

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

we wanted to ignore boolean return type of method.

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

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

关于java - 在 Java 中通过 lambda 返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38540481/

相关文章:

Java Hibernate暂时忽略带有条件的@ManyToOne注释

vb.net - 如何在 vb.net 中使用 Linq 选择单个对象

java - 序列化一个可运行对象

java - 如何多次实例化一个实现可运行并打开套接字的类?

java - 按锁定按钮时声音停止

java - 重写 ArrayList 添加方法时出现问题

java - 使用 log4j,如何记录到 Windows 控制台?

java - 如果流包含多个逗号分隔值,则拆分流

c# - 如何使用 linq 从 1 行数据构建对象?

java - 了解同步