Problema com generics (Eclipse x JDeveloper)

15 respostas
danieldestro

Algumas das minhas classes tem um código tipo o abaixo:

public <T extends Formatter> Class<T> getFormatterClass() { return Cep.class; }

No projeto do JDeveloper ele compila sem problemas. Já no Eclipse ele chia dizendo que não pode converter Class<Cep> para Class<T>.

Alguém sabe o porquê?

15 Respostas

T

Como é a declaração de Cep?

danieldestro

public class Cep implements Validator, Formatter { //... }

zinho

Daniel, será que o eclipse não está certo?
Não seria o caso de “… polymorphism applies only to the base type” (Kathy Sierra).

Dessa forma parece funcionar:

public Class<? extends Formatter> getFormatterClass() {  
		return Cep.class;  
	}
T

Parece um bug do compilador do JDeveloper. Usei o JDK 5.0 e 6.0 para o seguinte código:

interface Formatter {
}

class Cep implements Formatter {
}

class BugGenerics {

    public &lt;T extends Formatter&gt; Class &lt;T&gt; getFormatterClass() {
        return Cep.class;
    }

}

e ele deu "incompatible types", tal como o Eclipse reclamou. Ele não reclama se usar:

interface Formatter {
}

class Cep implements Formatter {
}

class BugGenerics {

    public Class &lt;? extends Formatter&gt; getFormatterClass() {
        return Cep.class;
    }

}
danieldestro

Funcionou no JDev, mas no Eclipse ainda tenho erros:

Class&lt;Formatter&gt; fclass = tag.getFormatterClass();

Type mismatch: cannot convert from Class<capture#1-of ? extends Formatter> to
Class<Formatter>

Bom, preciso dar uma melhor estudada em Generics… ainda me parece confusa essa sintaxe.

T

De fato, Class<Formatter> fclass só pode receber um argumento do tipo Class<Formatter>, não Class<? extends Formatter>.
Não é à toa que o pessoal do .NET inventou (no C# 3.0) a sintaxe var:

// se fosse em C#:
var fclass = tag.getFormatterClass();

onde "var" é uma abreviatura para o tipo correto, que neste caso é "Class <? extends Formatter>".

danieldestro

Se mudo para o código abaixo, funciona no Eclipse.

Class&lt;? extends Formatter&gt; fclass = tag.getFormatterClass();

No JDev dá erro:

Class&lt;? extends Formatter&gt; fclass = tag.getFormatterClass(); Formatter formatter = fclass.newInstance(); // erro aqui

T

Esse compilador do JDev está bem bugadinho, hein? Se ele usar o próprio javac, será que não é possível trocar a versão? Compilei o código com o JDK 5.0 e 6.0 e funciona direitinho.

interface Formatter {
}

class Cep implements Formatter {
}

class BugGenerics {

    public Class &lt;? extends Formatter&gt; getFormatterClass() {
        return Cep.class;
    }

    public static void main(String[] args) throws Exception {
        Class&lt;? extends Formatter&gt; fclass = new BugGenerics().getFormatterClass();
        Formatter fmt = fclass.newInstance();
    }
}
ddduran

O JDeveloper me parece que tem alguns problemas para interpretar generics
http://www.guj.com.br/posts/list/73259.java#385234

isso só vai funcionar assim

metodo

public Class <? extends Formatter> getFormatterClass()

e pra pegar o resultado

Class<? extends Formatter> clazz = c.getFormatterClass();

ddduran

danieldestro:
Se mudo para o código abaixo, funciona no Eclipse.

Class&lt;? extends Formatter&gt; fclass = tag.getFormatterClass();

No JDev dá erro:

Class&lt;? extends Formatter&gt; fclass = tag.getFormatterClass(); Formatter formatter = fclass.newInstance(); // erro aqui

qual o erro?
será que não é a falta do tratamento das exceções
InstantiationException e
IllegalAccessException?

zinho

É, realmente. Ainda segundo o livro da Kathy Sierra

There’s a very simple rule here?the type of the variable declaration must match the type you pass to the actual object type. If you declare List foo then whatever you assign to the foo reference MUST be of the generic type . Not a subtype of . Not a supertype of .Just .

Agora, esse erro no JDev é realmente estranho. Qual exception ele lança?

danieldestro

O JDev mostra erro no editor, porém acabei de descobrir que o código compila sem erros.
Se eu mudar para:

formatter = (Formatter) fclass.newInstance();

Ele nem mostra erro no editor e compila numa boa. No Eclipse também.

No final:

public Class&lt;? extends Formatter&gt; getFormatterClass() {
        return Cep.class;
    }

//...
Class&lt;? extends Formatter&gt; fclass = tag.getFormatterClass();
Formatter formatter = (Formatter) fclass.newInstance();
//...
ddduran

Se tiver que usar cast de qualquer jeito nem vale a pena usar generics

danieldestro

Na verdade não precisa usar. O Jdev compila também, mas o editor dele chia e você acha que está errado.

T

Conclusão: o compilador do JDeveloper (que deve ser o próprio Javac) e o editor do JDev não falam a mesma língua (se a Oracle tentasse rodar aquela suite de testes do Javac, para comprovar a compatibilidade com o javac, provavelmente não passaria.
Isso deve ser porque a equipe da Oracle que cuida da JVM da Oracle, e que tem acesso à suite de testes da Sun, não deve se falar com a equipe do JDeveloper.)
Alguém sabe se a Oracle ainda teima em ter sua própria versão da JVM ou eles desistiram?

Para evitar esses problemas, o Eclipse criou seu próprio compilador, para poder ser usado no editor também, e a equipe do NetBeans solicitou “gentilmente” à equipe do Javac que houvesse uma maneira de poder acessá-lo diretamente, para evitar esse esforço dobrado.

Criado 29 de novembro de 2007
Ultima resposta 29 de nov. de 2007
Respostas 15
Participantes 4