Warum ist diese Typrückschluss funktioniert nicht mit dieser Lambda-Ausdruck Szenario?

Ich habe ein seltsames Szenario, in dem Typrückschluss funktioniert nicht, da würde ich erwarten, dass bei der Verwendung eines lambda-Ausdrucks. Hier ist eine Annäherung an meine real-Szenario:

static class Value<T> {
}

@FunctionalInterface
interface Bar<T> {
  T apply(Value<T> value); //Change here resolves error
}

static class Foo {
  public static <T> T foo(Bar<T> callback) {
  }
}

void test() {
  Foo.foo(value -> true).booleanValue(); //Compile error here
}

Die compile-Fehler bekomme ich auf der zweiten bis letzten Zeile ist

Die Methode booleanValue() ist nicht definiert für den Typ Objekt

wenn ich warf die lambda Bar<Boolean>:

Foo.foo((Bar<Boolean>)value -> true).booleanValue();

oder wenn ich ändern Sie die Signatur der Methode von Bar.apply raw-Typen:

T apply(Value value);

dann das problem verschwindet. Die Art und Weise würde ich erwarten, dass dies funktioniert ist, dass:

  • Foo.foo nennen sollte schließen, ein Rückgabetyp boolean
  • value im lambda sollte geschlossen werden, um Value<Boolean>.

Warum nicht diese Schlußfolgerung funktioniert wie erwartet und wie kann ich dies ändern API machen, damit es funktioniert, wie erwartet?

  • Welche Java-Version Sie verwenden?
  • Java 1.8.0_25
  • Sie haben einfach ein "type mismatch", weil Boolean ist nicht ein Wert<Boolean>. Wie der compiler sollte in der Lage sein zu wissen, dass T einen Wert<T>? Und natürlich ist es auch nicht wissen, wie es ausgegangen Objekt. Blick auf die Funktion Interface-Methode anwenden. Wert ist eine konkrete Art, die in Zusammenhang mit Ihrem Bar-Schnittstelle.
  • Ich denke, das was du beschreibst ist die Grundlage für @fukanchik die Antwort von unten. Das problem dort ist, dass der compiler folgert Value<Object> statt Value<Boolean> das ist, was ich bin nach. Bitte fühlen Sie sich frei zu teilen irgendwelche Ideen auf, wie man es an die Arbeit.
  • Ich habe ein update gemacht auf meine Antwort, können Sie einen Blick zu haben.
  • Was ist, wenn Sie Boolean.TRUE statt true?
  • Keine änderung
  • Wenn Sie nicht wegwerfen der Rückgabetyp Foo.foo, die compiler nutzen könnte, der Zieltyp abgeleitet Schranken für T...
  • Auch ohne das Ziel geben, kann man visuell ableiten, welche den Rückgabetyp und die lambda-parameter geben sollte - was ich so erwartet, richtig?
  • Leider Typrückschluss ist nicht Gedankenlesen; es ist constraint solving. Die Frage ist also, Woher weiß der compiler, um seine Einschränkungen aus. Die lambda-Körper wird nicht verwendet, um generieren Einschränkungen (aus guten Gründen.) So, während es ist "offensichtlich", dass Sie meinte, dass T=boolean ist, dass die lambda-returns-boolean ist nicht als Eingang verwendet in Typ-Inferenz. Also Nein, der compiler hat nicht die notwendigen Informationen ableiten, dass T in diesem Fall mit dem return-type ignoriert.
  • Wenn der compiler nicht die lambda-Körper zu erzeugen Zwänge, warum dann nicht ändern Bar Verwendung einer raw - Value Art etwas ändern?
  • Raw-Typen sind viral. So dass die änderung der Signatur von apply (), um ein raw-Typ Ursachen der Inferenz zur Behandlung der lambda als roh-und jetzt, aus der Sicht der Inferenz, T erscheint nicht überall, so gibt es nichts zu folgern.
  • Ich bin mir nicht sicher, ob ich verstehe deine Erklärung. Wenn es nichts zu folgern, wie weiß der compiler magisch kommen mit Boolean als Typ für T wenn es instanziiert die Methode Signatur? Sieht es denn an der lambda-Körper in diesem Fall, oder ist etwas anderes passiert?

InformationsquelleAutor Josh Stone | 2015-07-05
Schreibe einen Kommentar