Questo è un esempio reale di un'API di librerie di terze parti, ma semplificato.
Compilato con Oracle JDK 8u72
Considera questi due metodi:
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
Entrambi riportano un avviso "non controllato" - capisco perché. La cosa che mi sconcerta è perché posso chiamare
Integer x = getCharSequence();
e si compila? Il compilatore dovrebbe sapere che Integer
non implementa CharSequence
. La chiamata a
Integer y = getString();
dà un errore (come previsto)
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
Qualcuno può spiegare perché questo comportamento dovrebbe essere considerato valido? Come sarebbe utile?
Il client non sa che questa chiamata non è sicura: il codice del client viene compilato senza preavviso. Perché la compilazione non dovrebbe avvisare di ciò / emettere un errore?
Inoltre, in cosa differisce da questo esempio:
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
Tentare di passare List<Integer>
genera un errore, come previsto:
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
Se questo viene segnalato come errore, perché Integer x = getCharSequence();
non lo è?
Integer x = getCharSequence();
verrà compilato, ma il casting su RHSInteger x = (Integer) getCharSequence();
non verrà compilato