46

このコードの違いは何ですか?

Supplier<LocalDate> s1 = LocalDate::now;
LocalDate s2 = LocalDate.now();

System.out.println(s1.get()); //2016-10-25
System.out.println(s2); //2016-10-25

Java 8 で関数型インターフェースの学習を開始しましたが、サプライヤの利点がわかりません。いつ、どのように、正確に、それらを使用する必要があります。サプライヤはパフォーマンスを向上させますか、それとも抽象化レベルでのメリットをもたらしますか?

回答ありがとうございます。また、検索を使用して必要なものが見つからなかったため、重複した質問ではありません。

更新 1: これのことですか?

    Supplier<Long> s1 = System::currentTimeMillis;
    Long s2 = System.currentTimeMillis();

    System.out.println(s1.get()); //1477411877817
    System.out.println(s2); //1477411877817
    try {
        Thread.sleep(3000l);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(s1.get()); //1477411880817 - different
    System.out.println(s2); //1477411877817
4

8 に答える 8

21

パフォーマンスが向上しないことは間違いありません。あなたの質問は次のようなものです: なぜ変数を使用するのですか? 必要なたびにすべてを再計算するだけです。右?

メソッドを何度も使用する必要があるが、構文が冗長である場合。

という名前のクラスがありMyAmazingClass、その中に という名前のメソッドMyEvenBetterMethod(静的) があり、コード内の 15 の異なる位置で 15 回呼び出す必要があるとします。もちろん、次のようなこともできます...

int myVar = MyAmazingClass.MyEvenBetterMethod();
// ...
int myOtherVar = MyAmazingClass.MyEvenBetterMethod();
// And so on...

...しかし、あなたもできる

Supplier<MyAmazingClass> shorter = MyAmazingClass::MyEvenBetterMethod;

int myVar = shorter.get();
// ...
int myOtherVar = shorter.get();
// And so on...
于 2016-10-25T16:13:10.627 に答える
10

機能インターフェースとメソッド参照を混同しています。Supplierは に似た単なるインターフェースでCallableあり、Java 5 以降で知っておく必要があります。唯一の違いは、 とは異なり、Callable.callチェックされた s をスローできることです。したがって、これらのインターフェースには同様の使用例があります。ExceptionSupplier.get

現在、これらのインターフェイスは機能インターフェイスでもあります。これは、インターフェイス メソッドが呼び出されたときに呼び出される既存のメソッドを指すメソッド参照として実装できることを意味します。

したがって、Java 8 より前は、次のように記述する必要がありました。

Future<Double> f=executorService.submit(new Callable<Double>() {
    public Double call() throws Exception {
        return calculatePI();
    }
});
/* do some other work */
Double result=f.get();

そして今、あなたは書くことができます

Future<Double> f=executorService.submit(() -> calculatePI());
/* do some other work */
Double result=f.get();

また

Future<Double> f=executorService.submit(MyClass::calculatePI);
/* do some other work */
Double result=f.get();

いつ使用する かという問題Callableはまったく変わっていません。

同様に、いつ使用するかという問題Supplierは、実装方法に依存するのではなく、使用する API に依存します。

CompletableFuture<Double> f=CompletableFuture.supplyAsync(MyClass::calculatePI);
/* do some other work */
Double result=f.join();// unlike Future.get, no checked exception to handle...
于 2016-10-25T16:32:58.520 に答える