2016-08-08 11 views
2

Dies ist eine verkürzte Probe meines Codes mein Punkt zu beweisen:Lambda und Generics: Warum kompiliert sich das?

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 sollte der Compiler, dass V in createCheck()String aus der Getter-Funktion kommen sollte, weshalb es über die sich beschweren sollte int. Oder umgekehrt.

Warum also kompiliert?

Antwort

7

Ihre Unterschrift ist:

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

Sie haben keine Schranken für T oder V so absolut alle Werte von T oder V würde kompilieren.

Sie zurückkehren ein BiPredicate<T, String> jedoch, so dass die isEqualTo Methode, um die String ref nimmt und vergleicht seine Gleichheit mit dem Object value - dies auch vollkommen legal ist, wie ich glaube, isEqualTo ein Object nimmt das Verhalten von Object.equals zu imitieren.


In Ihrem Beispiel:

createCheck(X::getStr, 123); 

V ist einfach Object als dass der engste Typ ist verpflichtet, die String und Integer anwenden können.


Hast du vielleicht bedeuten:

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

Nun, "mittlere", ja. Aber dann müsste ich eine Methode für jeden Typ kodieren, den ich als "value" übergeben möchte. Und das ist nicht das, was ich vorhatte ... – sjngm

+0

Ich kann sehen, was Sie versuchen, @sjngm zu tun, aber ich sehe keinen Weg, es sicher zu machen. Sie könnten versuchen, BiPredicate createCheck (Funktion func, V-Wert) '- aber das hat offensichtlich eine andere Rückkehr zu Ihrer ursprünglichen Methode. Dies würde im zweiten Fall zu einem "BiPredicate " führen; Es kann die Kompilierungsfehler verursachen, nach denen Sie suchen ... –

+0

Nein, 'BiPredicate ' wirkt sich auf die Parameter von 'test()' aus. – sjngm