Generics e reflection

Olá pessoal,

Bom, estou usando uma API(acho que pela descrição do problema alguns saberão qual é) que por algum motivo que desconheço quando vou criar um Dao o generico é da seguinte forma:

Dao<T,ID>

Onde T seria o tipo da entidade e ID o tipo do id da classe. Só que esse ID ao meu ver é totalmente desnecessário ja que posso descobrir por reflection. Então criei um metodo que fazia essa descoberta. Só que me deparei com o problema:

Como passo o tipo descoberto para o Dao<T,ID>. Meu metodo retorna um Class<?> e se chama getIdType(T classe) onde classe é a entidade. Quando tento fazer Dao<T, getIdType(classe)> não funciona. O que afinal devo passar quando estou instanciando um tipo generico? Isso abalou meus conhecimentos de generics :roll:

Fiz umas buscas mas nao encontrei nada, principalmente pela dificuldade de formular uma busca para tal.

Isso não funciona porque os Generics são aplicados em tempo de compilação do programa e não de execução. Essa maneira de fazer exigiria a execução do método getIdType() para obter o tipo, o que não faz nenhum sentido para o compilador.

Certo,

Alguma sugestao de como resolver isso? xD

Pq fica mt tosco passar como parametro pro meu metodo uma coisa que eu posso descobrir e livrar quem está chamando disso.

Você pode parametrizar a classe apenas pelo tipo da entidade (T) , e os métodos que precisam do ID seriam especialmente parametrizados com o tipo do ID.
Na maioria das situações essa solução vai se comportar exatamente como você quer, porque ele é capaz de deduzir o tipo do ID de acordo com o que foi passado no parâmetro.

Um exemplo básico, apenas com create() e find()

[code]public class GenericDaoTest {

public static void main(String[] args) {
	// Cria o DAO, parametrizado apenas pelo tipo da ENTIDADE, sem usar o tipo do ID
	GenericDao<Entidade> dao = new GenericDao<Entidade>(Entidade.class);
	
	// Sem novidades no create, ele não usa o ID de qualquer maneira
	Entidade e1 = new Entidade();
	dao.create(e1);

	Integer idToSearch = 10;

	// Chamando método genérico, passando o parâmetro do tipo do ID
	Entidade e2 = dao.<Integer>find(idToSearch);
	
	// Na verdade não precisa do tipo, ele é capaz de deduzir pelo
	// que foi passado no parâmetro!
	// No final o tipo do ID fica transparente.
	Entidade e3 = dao.find(idToSearch);
}

}

class Entidade {
Integer id;
String outroCampo;
}

class GenericDao {
Class entityClass;
EntityManager em; // Poderia tambem ser a sessao do hibernate

public GenericDao(Class<T> entityClass) {
	this.entityClass = entityClass;
}

// Metodo que nao precisa do ID. Ok, funciona normalmente
void create(T entity) {
	em.persist(entity);
}

// Metodo que precisa do ID é genérico, 
// parametrizado pelo tipo do ID
<ID_TYPE> T find(ID_TYPE id) {
	return em.find(entityClass, id);
}

}[/code]

[quote=gomesrod]Você pode parametrizar a classe apenas pelo tipo da entidade (T) , e os métodos que precisam do ID seriam especialmente parametrizados com o tipo do ID.
Na maioria das situações essa solução vai se comportar exatamente como você quer, porque ele é capaz de deduzir o tipo do ID de acordo com o que foi passado no parâmetro.[/quote]

Mas nesse caso qualquer tipo que eu passe por parâmetro vai ser considerado como o tipo do id, certo? A checagem do tipo do id meio que se perde. Se você passar o tipo errado, só vai descobrir em tempo de execução.

Eu ainda prefiro passar o T e o ID pro Dao, se as minhas entidades tiverem ids de tipos diferentes…

É verdade! Pensei na praticidade mas acaba perdendo em segurança.