[quote=Lavieri]Que o compilador some com o T, eu sei… so que da mesma forma que ele subistitui os T por Cidade e cria os métodos correspondentes…
ele poderia subistituir
candidate instanceof T
por
candidate instanceof Cidade
é tão simples substituir isso quando subistituir no resto, não entendo a dificuldade real de fazer isso… mais enfim… paciencia…[/quote]
Aí é que está o porém. O COMPILADOR NÃO FAZ ISSO. Ele substitui T por Object e ponto-final. Daí ele cria alguns casts e alguns métodos ocultos para lidar com a incompatibilidade.
Na verdade, a forma como generics foi implementado é uma gambiarra. E como toda boa gambiarra está cheia de problemas estranhos e regras obscuras. Eles implementaram assim para que não houvessem problemas de compatibilidade com java 1.4 e inferiores.
C++, por exemplo, faz essa substituição mais ou menos da mesma forma que você falou. Mas isso gera dois problemas:
- Você tem centenas de classes sintéticas. Em C++, coisas como List<Cachorro>, List<Gato> e List<Integer> são diferentes. Além disso, trabalhar com coringas (aquele ?) seria muito mais complexo no java (C++ não tem coringas). No java, como o generic é apagado, você tem List simplesmente.
- Problemas de compatibilidade com o java 1.4. Se o generic não fosse apagado do bytecode, seria necessário adicionar alguns atributos ocultos em diversas classes.
Além disso, há casos onde substituir não seria possível. Por exemplo:
public class Foo<T> {
public T foo(Object o) {
return (T) o; // ***
}
}public class Moo {
public static void main(String[] args) {
Object x = 42;
Foo<Integer> a = new Foo<Integer>();
a.foo(x);
x = "batatinha";
Foo<String> b = new Foo<String>();
b.foo(x);
}
}Aqui, essa substituição não funcionaria. Na linha com o ***, ele deveria colocar o que? Integer? String? A única coisa que dá é Object mesmo. Se fosse substituir por Integer ou por String, teria que fazer isso para cada objeto, e isso iria requerer uma classe para cada tipo de objeto. Ainda assim ia ter alguns probleminhas quando uma superclasse tivesse um generic em um método final. Outra alternativa seria simplesmente mandar a compatibilidade com o java 1.4 e inferiores para o espaço, mas uma das bandeiras do java é justamente a retrocompatibilidade.