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