Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Generics no DAO - Por quê?

Por quê no Bean, existe a necessidade de passar o ".class", já que a classe já está sendo passada para o DAO? exemplo: return new DAO(Autor.class).listatodos();

Fico no aguardo.

3 respostas

Como o DAO é genérico você precisa qual classe ele vai trabalhar. Mesmo que ele seja tipado, você não consegue o que foi passado nos diamantes em tempo de execução. Exemplo:

public class Dao<T>

Você não consegue acessar esse T e saber o que foi passado...

Oi Alberto, Sim, porém, por quê ele consegue interceptar apenas a<Classe ? Em todo e qualquer caso, sempre será necessário passar o .class?

solução!

Opa Thiago, explicando direitinho (e é uma explicação bem avançadinha e longa). Vamos lá: quando você usa o Generics, seja no DAO, como em qualquer outro lugar, você faz algo como:

class DAO<T> {
   public T carrega(Long id) {
     // código do método
  }
}

E com isso, para instanciar o DAO, você tem que fazer algo como:

DAO<Autor> daoAutor = new DAO<Autor>();

E com essa tipagem na instanciação, agora na hora de usar o DAO, tudo que era T (da nossa tipagem, virou Autor), ou seja, o retorno do método carrega que fiz ali, virou Autor para o caso do meu daoAutor, certo? Nada de excepcional até aqui.

Então você deve ter pensado: "Porque então eu não poderia fazer isso aqui lá no meu método carrega?"

   public T carrega(Long id) {
      Class c = T.class;
     // código do método
  }

Seria o mais lógico e mais simples, certo? Certo. O problema é que T não existe em tempo de execução. T não é uma variável apontando para uma instância do tipo Class. T nada mais é do que um placeholder. Ele só guarda o lugar ali para um tipo ser usado na hora da compilação, para garantir que só aceite retornos e parâmetros daquele tipo que foi definido com o T.

De novo, isso só acontece em tempo de compilação. Depois de seu código compilado, ou seja, na hora da execução, esse T não existe mais. Repara então que ele não é uma variável apontando para um objeto do tipo Class.

Isso é um conceito avançadíssimo do Java chamado Type Erasure (traduzindo livremente aqui, seria algo como "Desaparecimento do tipo").

Por esse motivo, você precisa passar para dentro do seu DAO o que falta, ou seja, a referência para a instância de Class. Por isso fazemos também o:

class DAO<T> {
  private Class<T> classe;
  DAO(Class<T> c) {
     this.classe = c;
  }
   public T carrega(Long id) {
     // código do método
  }
}

Agora, como é garantido pelo construtor que vai haver essa instância de Class sendo passada, ele existirá lá dentro, pois é justamente o que T não é, uma referência para um objeto do tipo Class.

Talvez seja meio confuso num primeiro momento, mas veja se consegue captar a ideia e qualquer dúvida que ficar, poste aí para nós te ajudarmos.

Abraços