2016-08-08 9 views
2

これが私のポイントを証明するために私のコードの短縮サンプルです:ラムダとジェネリックス:これはなぜコンパイルされますか?

public class Tmp { 

    static class X { 
    void setStr(String blah) { 
    } 
    String getStr() { 
     return null; 
    } 
    } 

    public void test() { 
    createCheck(X::getStr, ""); // supposed to compile 
    createCheck(X::getStr, 123); // rather not: int isn't String 
    } 

    private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) { 
    return new BiPredicate<T, String>() { 

     @Override 
     public boolean test(T t, String ref) { 
     assertThat(func.apply(t)) 
      .as(ref) 
      .isEqualTo(value); 
     return true; 
     } 

    }; 
    } 

} 

IMHO、コンパイラはcreateCheck()Vが、それは文句を言う必要がある理由ですゲッター機能から来るStringでなければならないことがわかりますint。または、それ以外の方法です。

これはなぜコンパイルされますか?

答えて

7

あなたのシグネチャは次のとおりです。

private <T, V> BiPredicate<T, String> createCheck(Function<T, V> func, V value) { 

あなたはとても絶対にTまたはVのいずれかの値がコンパイルうTまたはVには限界がありません。 isEqualTo方法はString refを取り、Object valueへの平等を比較して

ただしBiPredicate<T, String>戻る- 私はisEqualToObject.equalsの動作を模倣するObjectを取ると仮定して、これはまた、完全に合法です。あなたの例では


:それはStringIntegerに適用できるバインドタイトなタイプがあるよう

createCheck(X::getStr, 123); 

Vは単にObjectです。


あなたはおそらくもしかして:まあ

private <T> BiPredicate<T, String> createCheck(Function<T, String> func, String value) { 
+0

、はい、 "平均します"。しかし、その後、私は 'value'として渡す型ごとにメソッドをコーディングする必要があります。そして、それは私がやるべきことではありません... – sjngm

+0

あなたは@sjngmをやろうとしていますが、私はそれを安全に行う方法が見えません。 ' BiPredicate createCheck(関数 func、V値)'を試すことができますが、これは明らかに元のメソッドとは異なる戻り値を持っています。これは、2番目のケースでは 'BiPredicate 'となります。それはあなたが探しているコンパイルエラーを引き起こす可能性があります... –

+0

いいえ、 'BiPredicate 'は 'test()'のパラメータに影響します。 – sjngm

関連する問題