Ich bin auf etwas gestoßen, das mich beim Schreiben von Code stört. Ich habe die beiden Beispiele im folgenden Codebeispiel zusammengestellt.Inkompatible Typen: Klasse <Bar> kann nicht in Klasse <CAP#1> konvertiert werden, wobei CAP # 1 eine Variable vom Typ Fresh ist
Die Zeile cls1
verwendet einen Lambda-Ausdruck, kompiliert jedoch nicht, während die Zeile cls2
eine Methodenreferenzen verwendet und kompiliert. Ich weiß, dass ich keine Probleme habe, wenn ich nicht-generische Objekte verwende, aber hier verwende ich Generika und insbesondere Wildcards.
import java.lang.annotation.*;
import java.util.Optional;
public class MCVE {
static class Foo {}
static class Bar extends Foo {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
static @interface Baz { Class<? extends Foo> value(); }
@Baz(Bar.class)
static class Quz {}
// Lambda expression - doesn't compile
Class<? extends Foo> cls1 = Optional.ofNullable(Quz.class.getAnnotation(Baz.class))
.map(baz -> baz.value())
.orElse(Bar.class);
// Method reference - compiles
Class<? extends Foo> cls2 = Optional.ofNullable(Quz.class.getAnnotation(Baz.class))
.map(Baz::value)
.orElse(Bar.class);
}
In der Funktionalität machen beide Linien das gleiche. Ich verstehe einfach nicht, was unter dem Dach passiert, dass die Verwendung eines Lambda-Ausdrucks fehlschlägt, während eine Methodenreferenz kein Problem hat.
Für alle, die fragen werden, erhielten die Fehler während des folgenden Zusammenstellung:
MCVE.java:25: error: incompatible types: Class<Bar> cannot be converted to Class<CAP#1>
.orElse(Bar.class);
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Foo from capture of ? extends Foo
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Dies ist eher lakonisch und bietet keine extrem nützliche Information.
Bitte beachten Sie auch, dass ich meine Nachforschungen gemacht habe und dass dieser Fehler nicht derselbe ist wie in den "Ähnliche Fragen", die Sie auf der rechten Seite sehen können. Der interessante Teil hier ist "Fresh-Type Variable".
http://stackoverflow.com/questions/20543966/incompatible-types-and-fresh-type -Variable – Hosseini
Im Allgemeinen: Javas Typsystem ist in diesen Tagen so ziemlich eine Black Box, und es gibt nicht viele allgemeine Regeln darüber, wann explizite Typen notwendig und unnötig sind. –
@ Hosseini Vielen Dank für diesen Link. Es ist viel näher an dem, was ich erlebt habe, als alles, was ich in "Ähnliche Fragen" gesehen habe, es handelt sich um eine Aufgabe - was hier nicht relevant ist, denke ich - Es geht nicht um die Frage, warum es mit einem Lambda nicht OK ist. aber OK mit einer Methodenreferenz. –