Java Language `return` ne renvoie que de la méthode lambda, pas de la méthode externe


Exemple

La méthode return ne renvoie que de la méthode lambda et non de la méthode externe.

Attention, c'est différent de Scala et Kotlin!

void threeTimes(IntConsumer r) {
  for (int i = 0; i < 3; i++) {
    r.accept(i);
  }
}

void demo() {
  threeTimes(i -> {
    System.out.println(i);
    return; // Return from lambda to threeTimes only!
  });
}

Cela peut conduire à un comportement inattendu lors de la tentative d'écriture de constructions de langage propres, car dans les constructions intégrées telles que for boucles, le return se comporte différemment:

void demo2() {
  for (int i = 0; i < 3; i++) {
    System.out.println(i);
    return; // Return from 'demo2' entirely
  }
}

Dans Scala et Kotlin, la demo et la demo2 que 0 . Mais ce n'est pas plus cohérent. L’approche Java est compatible avec le refactoring et l’utilisation de classes - le return dans le code en haut et le code ci-dessous se comporte de la même façon:

void demo3() {
  threeTimes(new MyIntConsumer());
}

class MyIntConsumer implements IntConsumer {
  public void accept(int i) {
    System.out.println(i);
    return;
  }
}

Par conséquent, le Java return est plus compatible avec les méthodes de classe et refactoring, mais moins avec le for et while builtins, ceux - ci restent particulièrement.

De ce fait, les deux suivants sont équivalents en Java:

IntStream.range(1, 4)
    .map(x -> x * x)
    .forEach(System.out::println);
IntStream.range(1, 4)
    .map(x -> { return x * x; })
    .forEach(System.out::println);

De plus, l'utilisation de try-with-resources est sûre en Java:

class Resource implements AutoCloseable {
  public void close() { System.out.println("close()"); }
}

void executeAround(Consumer<Resource> f) {
  try (Resource r = new Resource()) {
    System.out.print("before ");
    f.accept(r);
    System.out.print("after ");
  }
}

void demo4() {
  executeAround(r -> {
    System.out.print("accept() ");
    return; // Does not return from demo4, but frees the resource.
  });
}

imprimera before accept() after close() . Dans la sémantique de Scala et Kotlin, les essais avec ressources ne seraient pas fermés, mais ils imprimeraient before accept() seulement.