dúvida generics

10 respostas
bruno_r_santana

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?

10 Respostas

bruno_r_santana

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.

rafadelnero
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.

bruno_r_santana

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.

A

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 .

bruno_r_santana

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?

A

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.

bruno_r_santana

Eu estava usando o Netbeans, mas ajustei e rodei pelo Eclipse agora esse código:

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");
    }
}

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

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 …

bruno_r_santana

Desculpe mas não entendi muito bem ainda.

A

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 :?

 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

Criado 3 de janeiro de 2013
Ultima resposta 3 de jan. de 2013
Respostas 10
Participantes 3