2017-11-16 19 views
0

コードはコンパイルしないでください。なぜ型推論はJavaのlambdaとメソッド参照で同じように動作しないのですか?

public class MyClass { 

........... 

    private void setEndDateOfValidStatusToCurrentTime(List<LifecycleStatus> oldStatuses, Date currentTime) 
    { 
     oldStatuses.stream() 
      .filter(oldStatus -> isValidNow(oldStatus, currentTime)) 
      .findFirst().ifPresent(oldStatus -> oldStatus.setValidToDate(currentTime)); 
    } 

    private boolean isValidNow(LifecycleStatus lifecycleStatus, Date currentTime) 
    { 
     Date start = lifecycleStatus.getValidFromDate(); 
     Date end = lifecycleStatus.getValidToDate(); 
     Date startTime = Optional.ofNullable(start).orElse(new Date(0L)); // BEGINNING OF TIME 
     Date endTime = Optional.ofNullable(end).orElse(new Date(Long.MAX_VALUE)); // END OF TIME 

     return startTime.before(currentTime) && endTime.after(currentTime); 
    } 

} 

理由: Iフィルタ方法は、それを必要とするので述語インタフェースを標的化するためにラムダにisValidNow()を使用しています。しかし、isValidNow()は2引数のメソッドであり、Predicateのtest()は1つの引数しか必要としません!

私はJavaコンパイラが型推論の力を持っていることを知っています。このような能力を持つスマートコンパイラは、isValidNow()を内部的に分解し、2番目の引数(currentTime)を安全に置き、最初の引数(oldStatus)だけを使ってPredicateでtest()を満たす実装を作り出すことを決定します。 。

代わりにメソッド参照を使用しようとすると、型推論が機能しないのはなぜですか?私は

filter(this::isValidNow) 

filter(oldStatus -> isValidNow(oldStatus, currentTime)) 

を交換する場合興味深いことに、私はこれらのコンパイラエラーを参照してください。

- The method filter(Predicate<? super LifecycleStatus>) in the type Stream<LifecycleStatus> is not applicable for the arguments 
(this::isValidNow) 
- MyClass does not define isValidNow(LifecycleStatus) that is applicable here 

答えて

3

oldStatus -> isValidNow(oldStatus, currentTime)は、ここでは、述語/ラムダで、かつ唯一の引数を取ります。後者はコンパイルされない理由である、確かthis::isValidNowと同じではありませんその(currentTimelocal variable from the enclosing scopeある。)

new Predicate<LifecycleStatus> { 
    boolean test(LifecycleStatus oldStatus) { 
     return isValidNow(oldStatus, currentTime); 
    } 
} 

:そのラムダは実効的に等価です。

+0

ラムダ式の右辺にある1つの引数の述語法テスト(T t)に従うために、私が望むだけ多くの引数を持つメソッドを使うことができますか?サイドには1つしかありませんか? – softwarelover

+0

@softwarelover - lambdaは(この場合)1つの引数と式の間のマッピングです。その式はあなたが望むものであれば何でもかまいません(型が正しいことを前提とします)。 –

+0

oldStatusが引数として渡されるPredicate実装の等価コードを参照してください。 currentTimeはどうですか? test()メソッドはisValidNow()を呼び出しますが、test()はcurrentTimeをどのように知っていますか?私はcurrentTimeの宣言を見ません。どうか明らかにしてください。 – softwarelover

関連する問題