packageGenerics;importjava.util.*;publicclassDeclare{publicstaticvoidmain(String[]args){Listl=newArrayList();//List<Object> l1 = new ArrayList<String>();test(l);}publicstaticvoidtest(List<String>list){list.add("5");}}
Alguém me explica porque é possível passar um List (sem uso de generic) para um método que usa Generic?
É que, diferentemente do .NET, os “generics” são construídos usando-se “erasure”, e basicamente (se você for analisar o código gerado pelo compilador) são uma forma complicada de pôr os “casts” corretos nos lugares certos.
Então você pode até chamar uma biblioteca Java antiga (1.4 ou anterior) sem ter o fonte, só o .jar ou .class, e ela funcionar perfeitamente, ou vice-versa, porque um ArrayList<String> é só um ArrayList antigo, mas com os casts acrescentados automaticamente pelo compilador.
saoj
Outra coisa que vc não vai conseguir fazer com Generics é instanciar via reflection um ArrayList<String>. Isso é impossível em Java. Não sei se em NET é possível… (Eu adoraria descobrir que estou enganado aqui…)
G
gk-bgh
thingol:
É possível sim, mas dá aqueles warnings.
É que, diferentemente do .NET, os “generics” são construídos usando-se “erasure”, e basicamente (se você for analisar o código gerado pelo compilador) são uma forma complicada de pôr os “casts” corretos nos lugares certos.
Então você pode até chamar uma biblioteca Java antiga (1.4 ou anterior) sem ter o fonte, só o .jar ou .class, e ela funcionar perfeitamente, ou vice-versa, porque um ArrayList<String> é só um ArrayList antigo, mas com os casts acrescentados automaticamente pelo compilador.
Mas do jeito que eu entendo o compilador verificaria o “tipo” do objeto que você esta passando para o método e o tipo que o método espera receber, compararia os dois e em caso de não serem iguais, daria um erro.
R
RafaelVS
gk-bgh:
Mas do jeito que eu entendo o compilador verificaria o “tipo” do objeto que você esta passando para o método e o tipo que o método espera receber, compararia os dois e em caso de não serem iguais, daria um erro.
Isso poderia ser feito, mas quebraria todos os códigos existentes nas versões anteriores. E, por uma decisão de projeto da linguagem, decidiram que isso não daria erro de compilação e apenas emitiria um warning (avisao, alerta, etc.).
G
gk-bgh
RafaelVS:
gk-bgh:
Mas do jeito que eu entendo o compilador verificaria o “tipo” do objeto que você esta passando para o método e o tipo que o método espera receber, compararia os dois e em caso de não serem iguais, daria um erro.
Isso poderia ser feito, mas quebraria todos os códigos existentes nas versões anteriores. E, por uma decisão de projeto da linguagem, decidiram que isso não daria erro de compilação e apenas emitiria um warning (avisao, alerta, etc.).
Não estou entendendo pelo seguinte…
porque o compilador não aceita passar um ArrayList<Object> para um método que aceita ArrayList<String> mas aceita passar um ArrayList para um método que aceita ArrayList<String>. Se fosse o type erasure o primeiro caso funcionaria, não?
[]s
Gunnar
T
thingol
O “generics” só funciona direito se você olhar todos os warnings e não deixar escapar nenhum.
No seu caso, você tentou passar um ArrayList para um método que requer um ArrayList<String> .
Um warning vai ser gerado, dizendo que ele não garante que realmente haja strings nesse arraylist de strings.
Vou dar um exemplo em que há um warning e então ocorre um ClassCastException em tempo de execução:
importjava.util.*;/**TesteMauUsoDeGenerics.java:14: warning: [unchecked] unchecked call to add(E) asa member of the raw type java.util.List inteiros.add (3); ^TesteMauUsoDeGenerics.java:15: warning: [unchecked] unchecked call to add(E) asa member of the raw type java.util.List inteiros.add (20); ^TesteMauUsoDeGenerics.java:16: warning: [unchecked] unchecked call to add(E) asa member of the raw type java.util.List inteiros.add ("Abobrinha"); ^TesteMauUsoDeGenerics.java:17: warning: [unchecked] unchecked conversionfound : java.util.Listrequired: java.util.List<java.lang.String> t.processarListaString (inteiros); ^4 warnings*/classTesteMauUsoDeGenerics{publicStringprocessarListaString(List<String>strings){StringBuffersb=newStringBuffer();for(Iterator<String>iter=strings.iterator();iter.hasNext();){sb.append(iter.next());// vai ocorrer um ClassCastException aqui no primeiro item da lista}returnsb.toString();}publicstaticvoidmain(String[]args){TesteMauUsoDeGenericst=newTesteMauUsoDeGenerics();Listinteiros=newArrayList<Integer>();inteiros.add(3);//-> warninginteiros.add(20);//-> warninginteiros.add("Abobrinha");//-> warningt.processarListaString(inteiros);//-> warning : [unchecked] unchecked conversion}}
R
RafaelVS
ArrayList para um método que aceita ArrayList acho que não deveria ser permitido (como de fato não é) ja que nem todo Object é String.
Pensando o contrário ArrayList para um método que aceita ArrayList, conceitualmente falando, Java permite isso, porém a sintaxe é diferente. Seria ArrayList para um método que aceita ArrayList<? extends Object>.