Este é um exemplo do mundo real de uma API de biblioteca de terceiros, mas simplificado.
Compilado com o Oracle JDK 8u72
Considere estes dois métodos:
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
Ambos relatam um aviso de "elenco não verificado" - eu entendo o porquê. O que me deixa perplexo é por que posso ligar
Integer x = getCharSequence();
e compila? O compilador deve saber que Integernão implementa CharSequence. A chamada para
Integer y = getString();
dá um erro (como esperado)
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
Alguém pode explicar por que esse comportamento seria considerado válido? Como isso seria útil?
O cliente não sabe que esta chamada é insegura - o código do cliente é compilado sem aviso. Por que a compilação não alertou sobre isso / emitiu um erro?
Além disso, como é diferente deste exemplo:
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
Tentar passar List<Integer>dá um erro, como esperado:
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 isso é relatado como um erro, por que Integer x = getCharSequence();não?
Integer x = getCharSequence();vai compilar, mas lançando sobre o RHSInteger x = (Integer) getCharSequence();falha compilação