Porém resolvi fazer o seguinte um cache de DAOs, onde adiciono os DAOs e um HashMap e depois só passar um metodo getDAO(…), o erro ocorre quando chamo o meto getDAO do código abaixo, o erro aponta para o código acima:
import java.util.HashMap;
import java.util.LinkedHashMap;
public class FactoryDAO {
private HashMap<Class<? extends BaseDTO>, BaseDAO<? extends BaseDTO>> listDAO;
private static FactoryDAO instance;
public static FactoryDAO getInstance() {
if (instance == null) {
instance = new FactoryDAO();
}
return instance;
}
public FactoryDAO() {
this.listDAO = new LinkedHashMap<>();
}
public void addDAO(BaseDAO<? extends BaseDTO> dao){
if (dao!=null) {
Class<? extends BaseDTO> classeDTO= dao.getObjectClassT();
if (this.listDAO.containsKey(classeDTO)==false){
this.listDAO.put(classeDTO, dao);
}
}
}
public BaseDAO<? extends BaseDTO> getDAO(Class<? extends BaseDTO> classeDTO){
return this.listDAO.get(classeDTO);
}
}
Não é tão simples assim bolar uma estrutura genérica para resolver tipos genéricos (digo por experiência própria). Depois de esfarelar a cabeça tentando, acabei por adaptar esta classe do Spring pra fazer isso:
Transformei a solução em uma DSL simples com meu projeto (está na minha assinatura), se interessar:
T type = Reflection.reflect().genericType("T").in(this)
Basicamente isso poderia ser adicionado no construtor de BaseDAO e o type ser retornado naquele método getObjectClassT.
O lance aqui é que você precisa informar o nome utilizado para a tipagem genérica porque é preciso extrair um mapa contendo cada nome mapeado para seu tipo resolvido (lembrando que essas informações somente estão presentes nos bytecodes de definição dos tipos - classe, interface, etc.). Isso acaba deixando você definir mais de um tipo genérico quando necessário.
Praticamente todos os truques de Reflection estão presentes no Spring, é legal dar uma olhada no fonte deles pra ver como solucionam problemas como obter nome dos parametros de métodos, obter o método genérico a partir do método bridge, e por aí vai.
T type = Reflection.reflect().genericType("T").in(this)
O código acima foi tirado do Spring? Pagaste uma das classes dele e adaptaste?
Se eu chamar new BaseDAO().getList() o erro ocorre, mas se utilizar uma classe filha new MestreDAO.getList() o erro não ocorre, não estou entendendo o porque.
A diferença que no MestreDAO o tipo generico já é definido na assinatura da classe.
Não tem como fazer o que quero pelo visto.
Pois se eu fizer algo como “public class MestreDAO extends BaseDAO{…”, e passar FactoryDAO.getInstance().addDAO(new MestreDAO());, funciona tudo perfeitamente.
Acho que isso se deve pelo parametro já ter sido passado em tempo de compilação, o que é uma pena. Já que o BaseDAO fazia tudo não queria obrigar o usuario a ter de instanciar uma classe para utiliza-lo, mas não tem como neste caso.
[quote=Michel.Montenegro]T type = Reflection.reflect().genericType("T").in(this)
O código acima foi tirado do Spring? Pagaste uma das classes dele e adaptaste?
Se eu chamar new BaseDAO().getList() o erro ocorre, mas se utilizar uma classe filha new MestreDAO.getList() o erro não ocorre, não estou entendendo o porque.
A diferença que no MestreDAO o tipo generico já é definido na assinatura da classe.
[/quote]
Ah tá, agora clareou tudo pra mim.
Primeiramente, aquele código foi adaptado por mim, uma das implementações da interface fluente de reflexão usa uma classe adaptada do Spring (aquela cujo javadoc postei na mensagem anterior).
Quanto ao seu problema, atente para este ponto na minha mensagem anterior:
Quando você usa new BaseDAO, não está definindo um tipo, ou seja, o se perde na compilação. Já o MestreDAO tem o tipo generico já definido na assinatura da classe, por isso ele não se perde em compilação.
Você, obrigatoriamente, precisa declarar um tipo para obter o tipo genérico. Você pode fazer new BaseDAO(){}.getList() ou criar uma classe filha de BaseDAO tal qual a MestreDAO. Eu, particularmente, usaria a segunda solução.
Obrigad, vou ver o que fizeste.
A slução desse rapaz, acho que também deve funcionar, neste caso em especial onde não tem problema ser uma classe anonima, já que acesso a referencia via a chave do hasmap. http://guj.com.br/java/87606-extrair-nome-do-tipo-generico#1520886
[quote=hvivox]Então o pulo do gato para solucionar o problema é acrescentar as chaves {} no final da chamada do seu dao generico
exemplo:
IDataAcessObject<Cargo> daoCargo = new DataAccessObject<Cargo>(){};
ok?[/quote]
Isso resolve, mas não é nem um pouco aconselhável. Além de criar uma classe anônima em cada ponto em que escrever isso e ajudar a entupir o ClassLoader desnecessariamente, o código fica com uma cara muito ruim e propenso a erros (é muito fácil esquecer as chaves quando elas não são algo comum nesse contexto). Como eu disse no post mais acima, é preferível usar uma subclasse a usar as chaves.