2016-07-23 12 views
5

今まで私は必要なすべての回答を見つけることができますが、この1つは私を混乱させます。Javaでラムダの戻り値

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研究ガイド(試験1Z0-808)この本は、これら2本の線が同等であることを述べている:

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

が、これは舞台裏で、Javaが追加されます、という意味ではないのは、私たちはサンプルコードを持っているとしましょうキーワード返信最初の場合は?

答えがYESであれば、どのようにコードのコンパイル(他のすべてが適切な場所にあると想像)次:

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

我々はための署名がを実行することを知っていて、Runnableの実行がある場合:

void execute(Runnable command) 
void run() 

答えがNOの場合、Javaが何かを返す必要がある時としないときをJavaがどのように知っているか?たぶん

a -> a.canHop() 

場合には、メソッドのブール戻り値の型を無視したかったです。

+2

run()がvoidを返すので、Runnableのケースでは戻り値の型を無視できることがわかります。 test()はvoidを返さないため、CheckAnimalの場合は戻り値の型を無視してはいけないことがわかります。 –

+1

lambadaは、メソッドに返される型が含まれている場合、ラムダはそうでなければ提供しません。メソッドを書くためのショートカットですので、自分自身を混同しないでください。 – emotionlessbananas

答えて

9

これは舞台裏で、Javaが最初のケースでは、コードにキーワードリターンを追加し、ということを意味していますか?

いいえ、コンパイラはバイトコードを生成し、同じバイトコードを生成することがありますが、構文を変更せずに再度コンパイルします。

メソッドのブール型戻り値の型を無視したかったのです。

これは、考慮している機能インタフェースに基づいて値を無視するかどうかを選択できます。可能であれば

a -> a.canHop() 

は、コンテキストに基づいて

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

又は

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

かもしれない、しかし、それは最初に有利に働きます。

はここに長い一例であり、あなたはそれが自分自身を試してCallable<Integer>

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

をだ見ることができる戻り値の型を保存

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

ExecutorService.submit(Callable<T>)ExecutorService.submit(Runnable)を考えてみましょう。

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 

最初submitCallableのでFuture.get()戻り2

あることにRunnableようFuture.get()戻りnull

submitデフォルトをとりますRunnableそうFuture.get()戻りnull

+0

実行時にRunnableを取る場合:es.execute (()→counter ++);それは副作用として考慮されていますか? – Freeman

+0

@Freeman値を返さないメソッドは、副作用のみを持つことができます。 –

0

returnステートメントの範囲については混乱しています。 returnステートメント(コンパイラによってバイトコードとして挿入されるか、プログラマによってソースコードとして挿入されるか)は、ラムダから返され、ラムダを呼び出すメソッドからは返されません。

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

のみ単一のステートメントを指定する場合はい、その値が自動的にラムダから返されなければなりませんので、第三submitvoid戻り値にすることができます。

次に、Runnableは機能インターフェイスであるため、ラムダとして定義できます。戻り値の型はvoidなので、ラムダ内の戻り値は無視されます。