Valeur renvoyée par lambda en Java

Jusqu’à présent, je parviens à trouver toutes les réponses dont j’ai besoin, mais celle-ci me déroute. Disons que nous avons un exemple de code:

public class Animal { private Ssortingng species; private boolean canHop; private boolean canSwim; public Animal(Ssortingng speciesName, boolean hopper, boolean swimmer) { species = speciesName; canHop = hopper; canSwim = swimmer; } public boolean canHop() { return canHop; } public boolean canSwim() { return canSwim; } public Ssortingng toSsortingng() { 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(Ssortingng[] args) { print(new Animal("fish", false, true), a -> a.canHop()); } } 

Le guide d’étude OCA (Examen 1Z0-808) indique que ces deux lignes sont équivalentes:

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

Est-ce que cela signifie que, dans les coulisses, Java ajoute le mot clé return au code dans le premier cas?

Si la réponse est OUI, alors comment le code suivant comstackra-t-il (imaginez que tout le rest est à sa place):

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

si nous soaps que les signatures pour exécuter et exécuter Runnable sont:

 void execute(Runnable command) void run() 

Si la réponse est NON, comment Java sait-il quand il doit retourner quelque chose et quand ne pas le faire? Peut-être dans

 a -> a.canHop() 

Dans ce cas, nous voulions ignorer le type de méthode boolean return.

Est-ce que cela signifie que, dans les coulisses, Java ajoute le mot clé return au code dans le premier cas?

Non, le compilateur génère du code octet. Il peut générer le même code octet, mais il ne modifie pas la syntaxe et ne le recomstack pas à nouveau.

nous voulions ignorer le type de méthode boolean return.

Il a la possibilité d’ignorer une valeur en fonction des interfaces fonctionnelles envisagées.

 a -> a.canHop() 

pourrait être

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

ou

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

basé sur le contexte, cependant il privilégie le premier si possible.

Envisagez ExecutorService.submit(Callable) et ExecutorService.submit(Runnable)

 ExecutorService es = Executors.newSingleThreadExecutor(); es.execute(() -> counter++); // has to be Runnable es.submit(() -> counter++); // Callable or Runnable? 

En enregistrant le type de retour, vous pouvez voir que c’est un Callable

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

Pour vous essayer, voici un exemple plus long.

 static int counter = 0; public static void main(Ssortingng[] 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 final Future 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(); } 

estampes

 null 2 counter: 3 null 

Le premier Future.get() prend un Runnable afin que Future.get() renvoie null

Le second submit défaut à Future.get() donc Future.get() renvoie 2

Le troisième submit ne peut être qu’une void retour void , il doit donc être un Runnable pour que Future.get() renvoie null

Oui, lorsque vous ne spécifiez qu’une seule instruction, sa valeur est automatiquement renvoyée par le lambda.

Puis, puisque Runnable est une interface fonctionnelle, il peut être défini comme un lambda. Le type de retour est void , donc toute valeur de retour dans le lambda sera ignorée.

Vous êtes confus quant à la scope de l’instruction return . L’instruction return (qu’elle soit insérée en tant que bytecode par le compilateur ou en tant que code source par le programmeur) retourne depuis le lambda, et non depuis la méthode qui appelle le lambda.

 void foo() { Supplier s = () -> { return "bar" }; Ssortingng 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"); }