Ajuda Reflection

17 respostas
J

Bom estou passando um código C# para Java. Esse código usa reflection.
C#

public static List<TEntidade> Consultar<TEntidade>(){

em java fiz assim:

public static <T extends Object> List<T> Select() {

Eu usei esse estilo de declaração nos metodos Insert e Update, e funciona. Mas acho que para esse consultar não vai dar certo, pois mais abaixo do codigo C# vem:

string nomeTabela; if (typeof(TEntidade).Name[typeof(TEntidade).Name.Length - 1].Equals('s')) { nomeTabela = typeof(TEntidade).Name; } else { nomeTabela = typeof(TEntidade).Name + "s"; }

Essa parte do “typeof(TEntidade)…” que não sei como passar pra java. Alguém tem alguma sugestão?

17 Respostas

M

use o instanceof

if (objA instanceof objB) {

}

J

mfp.c:
use o instanceof

if (objA instanceof objB) {

}


Mas como eu pegaria o nome do objeto? com esse instanceof não dá pra colocar “.getName()”, ou dá?

[color=darkblue]Porém, tanto faz, pois não vai dar certo. Em C# a chamada para o metodo é:[/color]

Controller.Consultar<objetoEntidade>();

[color=darkblue]Em Java, quando fiz o metodo Insert, com assinatura:[/color]

private static <T extends Object> long Insert(T object) {

[color=darkblue]Só dá pra chamar assim:[/color] Controller.Insert(objetoEntidade);

[color=darkblue]Ou seja, eu não falo quem é T. Portanto, na chamada de Select, eu teria que fazer:[/color] Controller.Select();
[color=darkblue]Mas Select o que? O que eu vou selecionar? De qual tabela vou puxar? Não tem como saber, mas em C# tinha já que eu fazia “”.
Alguém sabe outro modo de se implementar isso?[/color]

H

Olha, não verifiquei pq nao to sem java aqui, mas creio que o método pra pegar o nome da classe é “Objeto.className()

Felagund

Para pegar o nome faz assim

if (objA instanceof objB) {
 objB aux = (objB) objA;
 aux.getName();

}

Cara os códigos que vc esta mostrando estão complementamente bagunçados, vc pode fazer igual do mesmo jeito em Java e em C# muitas coisas, o T é só um meio de dizer, esse metodo aceita qualquer coisa.

Faça um exemplo so, por exemplo e vamos ajuda-lo a fazer.

J

Vou simplificar.
Eu preciso fazer um método genérico que retorne uma lista de algum objeto. Como seria a assinatura desse método para que a chamada dele fosse assim:

NomeDaClasse.NomeDoMetodo(parametros);
Exemplo: Controller.Consultar();

Tem como fazer isso em java?

Felagund

JobaDiniz:
Vou simplificar.
Eu preciso fazer um método genérico que retorne uma lista de algum objeto. Como seria a assinatura desse método para que a chamada dele fosse assim:

NomeDaClasse.NomeDoMetodo(parametros);
Exemplo: Controller.Consultar();

Tem como fazer isso em java?

Agora sim meu filho xegamos em uma linguagem comum :slight_smile:

public class NomeDaClasse{
   public static <T> T Consultar(){
      //seu código aqui
   }
}

Assim tudo que vc precisa fazer é isso aqui

List<Livro> livros = NomeDaClasse.Consultar();

Se não me falha a memoria é so fazer isso.

Se der algum erro poste aqui e tentamos resolver

J

Ok. Agora vamos pular para o próximo passo :smiley:
Agora eu preciso pegar o nome do objeto T.

public static <T> List<T> Consultar(){
          //pegar o nome do objeto T.
          //com o nome eu posso saber qual tabela do banco vou consultar.
}

Pelo que vi, não dá pra fazer isso do jeito que vc mostrou na outra mensagem, pois eu não sei de que tipo é o objeto, pode ser qualquer um.

if(T instanceof /*Várias possibilidades*/)

Deu pra entender?

Felagund

Cara acredito que não de para vc pegar o nome de um objeto Tipo (T), tentei ver aqui e não consegui, o que vc pode fazer é passar o nome como parametro no metodo

public static &lt;T&gt; List&lt;T&gt; Consultar(String tableName){  
           //pegar o nome do objeto T.  
          //com o nome eu posso saber qual tabela do banco vou consultar.  
 }

como de todo o modo vc vai informar o tipo do objeto
vc vai saber qual é o tipo sempre
por ex:

List&lt;Livro&gt; livros = Consultar("livro");

vc esta usando um tipo ja informando que vc save qual tipo é vc tbm pode passar uma classe
e usar o getName() da classe por exemplo Livro.class, e pegar o nome da classe que retornará “Livro”.

Ja ouviu falar em Hibernate? pode ser uma boa solução para sua aplicação, ORM são uma mão na roda, muito bom.

[]'s

J

Já ouvi de nome, mas nunca li nada a respeito. Minha aplicação é desktop. A solução vai ser mesmo passar Livro.class

EDIT: Aliás, como ficaria o parametro pra receber Livro.class? T.class não dá certo…qualquer maneira, se não der faço com string mesmo.

vlw.

Felagund
public static &lt;T&gt; List&lt;T&gt; Consultar(Class classe){
  //pesquise aqui
}

de uma olhada em Hibernate.org, ele é um ORM muito bom, vc não precisa fazer SQLs ele faz tudo sozinho, vc manipula somente objetos.

[]'s

J

Existe algo parecido com isso em Java:

Controller.Consultar<Livros>(livro => livro.Nome == "Java");

O método me devolverá livros, tais que o nome seja “Java”.

Ou seja, eu faria algo como:

Controller.Consultar(Livros.class,....);

Tipo, o argumento é uma query. Existe isso? Ou tem algo semelhante?

71C4700

Com nossa caro amigo Felagund falou.
Vc podeira partir pra um ORM como o Hibernate ai vc poderia utilizar o Criteria que ajuda em consultas de entidades!!!
Caso contrario vc deve bolar uma maneira de gerar estas query em tempo de execução!

erdanielli

Melhor ainda seria tipar o argumento com Generics e evitar de vez ClassCastException. Tente assim:

import java.util.ArrayList;
import java.util.List;

public class Main {
	public static void main(String[] args) {
		List&lt;String&gt; stringList = getListOf(String.class);
		System.out.println(stringList);
	}
	public static &lt;T&gt; List&lt;T&gt; getListOf(Class&lt;T&gt; clazz) {
		String name = clazz.getName();
		System.out.println(name);
		return new ArrayList&lt;T&gt;();
	}
}
J
Vlw pela dica erdanielli.

Não vou usar hibernate. Estou brincando com o Java. Estava vendo se era possível passar o código que tinha de C# para Java.

Os métodos do Reflection são praticamente os mesmos, porém Java não tem tudo que o C# tem. Por exemplo, ambos tem a classe List, que na verdd em Java é interface List e a classe ArrayListEm C# existe um método dessa classe que é bastante útil:

List lista = new List();

lista.Where(entidade => entidade.id == 24);

Existe tbm lista.Max(); Pega o maximo segundo uma condição.

Pelo que vi, Java não possui tal tipo de estrutura.

erdanielli

Realmente a API de Collections do Java não possui essas funcionalidades que vc mencionou. Porém, nada impede vc de criar algo parecido. Saca só:

abstract class CollectionUtils {
	static <E> List<E> subconjunto(List<E> list, ListItemFilter<E> filter) {
		if (list == null) {
			return null;
		}		
		List<E> result = new ArrayList<E>();
		
		for (E item : list) {
			if (filter.matches(item)) {
				result.add(item);
			}
		}
		return result;
	}
}

interface ListItemFilter<T> {
	boolean matches(T item);
}

Agora um caso de uso: Vamos listar somente os livros lançados no ano de 2008

class CollectionUtilsTest {
	public static void main(String[] args) {
		List<Livro> livros = Arrays.asList(
				new Livro("Head First Java", "Kathy Sierra", 2005),
				new Livro("Effective Java", "Joshua Bloch", 2008)
		);
		
		List<Livro> livrosDoAnoDe2008 = CollectionUtils.subconjunto(livros, new ListItemFilter<Livro>() {
			public boolean matches(Livro item) {
				return item.ano == 2008;
			}
		});
		
		// Imprime somente "[Effective Java]"
		System.out.println(livrosDoAnoDe2008);
	}
}

class Livro {
	String titulo;
	String autor;
	int ano;

	public Livro(String titulo, String autor, int ano) {
		this.titulo = titulo;
		this.autor = autor;
		this.ano = ano;
	}
	
	public String toString() {
		return titulo;
	}
}

Pena que as Closures ficaram de fora do Java 7. Seriam perfeitas para este exemplo!

Abraço!

Felagund

Na verdade uma vantagem do C# sobre o Java é justamente o LINQ e as Expressões lambdas, essa segundas são conhecidas na comunidade Java como Closures. E como o Java não é determinado por uma unica empresa como o C#, a Sun esta estudando as propostas de Closures, para ver qual é a melhor, sem drasticamente a estrutura, coisa q a M$ ta nem ai se vc vai ter que reescrever um sistema inteiro :P.

Realmente não suporte a esse where, como no C#, seria ate uma ideia bacana de se implementar. Porém atualmente a unica solução é percorrer a lista e retronar os valores.

[]'s

J

hum…encontrei esse site…não baixei o conteudo, mas parece que está implementado algo sobre Closures
http://www.javac.info/

EDIT: Baixei o arquivo. Veio um .jar e alguns outros arquivos como java, javadoc, javac (com extensões .bat e .arquivo).
DÚVIDA: Como eu faço pra usar o que foi implementado nesse arquivo nos meus projetos?

Criado 21 de fevereiro de 2009
Ultima resposta 27 de fev. de 2009
Respostas 17
Participantes 6