Dies ist ein reales Beispiel aus einer Bibliotheks-API eines Drittanbieters, jedoch vereinfacht.
Kompiliert mit Oracle JDK 8u72
Betrachten Sie diese beiden Methoden:
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
Beide melden eine Warnung "ungeprüfte Besetzung" - ich verstehe warum. Was mich verblüfft, ist, warum ich anrufen kann
Integer x = getCharSequence();
und es kompiliert? Der Compiler sollte wissen, dass Integer
dies nicht implementiert wird CharSequence
. Der Anruf an
Integer y = getString();
gibt einen Fehler (wie erwartet)
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
Kann jemand erklären, warum dieses Verhalten als gültig angesehen wird? Wie wäre es nützlich?
Der Client weiß nicht, dass dieser Aufruf unsicher ist - der Code des Clients wird ohne Warnung kompiliert. Warum warnt die Kompilierung nicht davor / gibt einen Fehler aus?
Wie unterscheidet es sich von diesem Beispiel:
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
Der Versuch, zu bestehen List<Integer>
, führt erwartungsgemäß zu einem Fehler:
method doCharSequence in class generic.GenericTest cannot be applied to given types; required: java.util.List<X> found: java.util.List<java.lang.Integer> reason: inference variable X has incompatible bounds equality constraints: java.lang.Integer upper bounds: java.lang.CharSequence
Wenn dies als Fehler gemeldet wird, warum Integer x = getCharSequence();
nicht?
Integer x = getCharSequence();
wird kompiliert, aber Casting auf der RHSInteger x = (Integer) getCharSequence();
schlägt fehl kompilieren