Olá,
Estou estudando para certificação e vi no livro que podemos ter uma interface genérica e um método static genérico também. Tentei fazer um código para ver como funciona na prática. Montei esse código:
public interface InterfaceGenerica<X extends Number, Y extends Number> {
void somaNumeros(X x, Y y);
}
public class ImplementacaoGenerica implements InterfaceGenerica<Double, Integer> {
public void somaNumeros(Double d, Integer i){
System.out.println(d + i);
}
static public <T, U> void concatenarTextos(T t, U u){
System.out.println((String)t + (String)u);
}
static public void main(String... args){
new ImplementacaoGenerica().somaNumeros(2.1, 1);
concatenarTextos("Teste", " com generics");
}
}
Compila OK. O problema é quando tento fazer isso:
static public <T super String, U super String> void concatenarTextos(T t, U u){
System.out.println(t + u);
}
Gera erro:
java.lang.ClassFormatError: Duplicate field name&signature in class file certificacao/generics/ImplementacaoGenerica
Porque?
Outra coisa também. Alguém poderia me explicar onde uma interface genérica ou um método static genérico são úteis? Alguém tem um exemplo mais funcional e útil melhor do que o meu?
Obrigado.
static public <T super String, U super String> void concatenarTextos(T t, U u){
System.out.println(t + u);
}
Não sei onde você colocou esse outro método, mas métodos estáticos não podem ser sobrescritos talvez seja isso o erro.
rafadelnero, esse outro método que você não achou não compila, por isso deixei no meu código assim:
static public <T, U> void concatenarTextos(T t, U u){
System.out.println((String)t + (String)u);
}
Mas quando troco o método acima que compila pelo método:
static public <T super String, U super String> void concatenarTextos(T t, U u){
System.out.println(t + u);
}
dá erro. Sacou? Queria saber o motivo do erro, pois o código me parece normal, não consigo identificar qual o problema com o código.
Olá o erro ocorre porque vc ta usando soma para tipos Genéricos, e daí o compilador não entende se é uma concatenação ou uma soma matemática, já quando vc faz um downcast para String ele entende que é uma concatenação, se fosse para Number ele entederia como soma.
Se vc colocar somente System.out.print(t); e depois system.out.println(u); vai funcionar .
Eu já tentei comentar essa linha
mas o erro continua. O erro parece ser na declaração:
Tem algo errado nessa declaração de método?
não o problema não é a declaração do método genérico e sim na hora de dar o Println();
vc colocou uma soma t+ u , Como o compilador não sabe ql operação está sendo realizado se é de concatenação ou de soma ele acusa o erro . Tente colocar uma string no meio das variáveis locais t e u, tipo: t + " qualquer coisa " + u , ai da certo, pois é uma operação de concatenação.
Eu estava usando o Netbeans, mas ajustei e rodei pelo Eclipse agora esse código:
[code]interface InterfaceGenerica<X extends Number, Y extends Number> {
void somaNumeros(X x, Y y);
}
public class ImplementacaoGenerica implements InterfaceGenerica<Double, Integer> {
public void somaNumeros(Double d, Integer i) {
System.out.println(d + i);
}
static public <T super String, U super String> void concatenarTextos(T t, U u) {
System.out.println(t + " " + u);
}
static public void main(String... args) {
new ImplementacaoGenerica().somaNumeros(2.1, 1);
concatenarTextos("Teste", " com generics");
}
}[/code]
Deu esse erro agora:
Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The method concatenarTextos(T, U) from the type ImplementacaoGenerica refers to the missing type T
at ImplementacaoGenerica.main(ImplementacaoGenerica.java:17)
Se passo o mouse em cima da palavra super aparece: “Syntax error on token super , , expected”
Qual o problema desse código?
Obrigado.
A é q java não permite que se use limite inferior para tipos genéricos, tal como exemplo1 . a razão disso talvez seja que o compilador permitiria usar objetos do tipo ou mas não permitiria ou , mas como não permitiria se um é um Number e por ai vai , seria uma ambiguidade na linguagem.
No entanto java permite coisas do tipo List<? super Number> lista =new ArrayList();
lista.add(3.2) ; lista(new Long(222L)); e por ai vai …
Desculpe mas não entendi muito bem ainda.
Essa é uma ótima pergunta, eu também não sei explicar na verdade só sei que as regras são essas : ponto de interrogação + super somente para variáveis de referência e tipos parametrizaveis somente para metodos e classes :?
Dá uma olhada nesse exemplo :
class A{}
class GenClass{
public A<? super T> getNow(A<? super T> a){
return new A();
}
}
Compila ?
Sim , pois o uso de tipos parametrizáveis é somente nas classes e nos métodos nas variáveis usa-se a notação de interrogação + super.
Ainda sim é complicado pois como seria a descrição desse exemplo a classe A do tipo parametrizado E. A classe GenClass com tipo parametrizável E que estende A . Ela possui um método getNow que declara um tipo parametrizável T que estende E também e retorna A , sendo A qualquer tipo superior da hierarquia do T . Só que lembre que E estende A então T estende também A , certo? Então o parâmetro para o método getNow poderia ser qq tipo E ou tipo A ou qualquer super de T (para o tipo parametrizável) .
Agora porque da regra realmente não sei pergunta na parte avançada do Fórum .
Abraços