Java e Reflection

Assunto: Como utilizar essa poderosa API do java para saber, em tempo de execução, informações sobre classes que você não tinha conhecimento prévio. Como invocar e construir objetos destas classes?

Você pode ler este tutorial na íntegra http://www.guj.com.br/java.artigo.10.1.guj

Por favor, coloque as suas dúvidas e seus comentários sobre este tutorial aqui.
Sinta-se livre para fazer qualquer tipo de pergunta, desta maneira você estará nos ajudando e aos outros usuários!

Opa.

Tentei utilizar reflection para inicializar variáveis, conforme o exemplo mas, não me dei bem.
Nos meus em Value Beans eu sempre crio um método init(), para “zerar” o valor da variáveis antes de utilizá-las, e executo ele no construtor do Value Bean. p. Ex.:

private void init(){ var1 = nul; var2= -1; ... }

Eu não entendi que objeto é este que tem q ser passado para os métodos get e set do Filed.
Apelei pra tentativa-erro pra descobrir mas, sempre é disperada uma IllegalArgumentException.
O que é o maldito “field2 f2obj = new field2();” do exemplo (código abaixo)?

[code]import java.lang.reflect.*;

public class AlteraValorCampo {

public double d;

public static void main(String args[]) {
    try {
        Class cls = Class.forName("AlteraValorCampo");
        Field fld = cls.getField("d");
        field2 f2obj = new field2();
        System.out.println("d = " + f2obj.d);
        fld.setDouble(f2obj, 12.34);
        System.out.println("d = " + f2obj.d);
    }
    catch (Throwable e) {
        System.err.println(e);
    }
}

}[/code]

Eh que isso eh abstrato.

O Field2, poderia ser uma String, por exemplo.
Ai voce pega uma referencia a esse campo, atraves do getField.

Depois, voce mexe nessa String, e ai, por reflection, seta essa String em determinado objeto da classe que voce esta refletindo.

Entendeu?

Olá.

Eu até pensei ter entendido, qdo li isto na API. Só que não consegui corrigir o erro, portanto não entendi. Desculpa a minha ignorância. :slight_smile:
Vai aí o código que dispara IllegalArgumentException:

[code]
import java.lang.reflect.*;
public class ReflectionTest {
public String testeStr = “Uma string”;

public ReflectionTest () {
	init();
}

protected void init() {
	try {
		Class cls = Class.forName( getClass().getName().toString() );
		
		Field field = cls.getField( "testeStr" );
		String str = new String();
		
		field.set( str, (String)"String modificada");

//tbm testei:
//field.set( field, (String)“String modificada”);

	System.out.println( testeStr );

}
catch (Throwable e) {
System.err.println(e);
}

}

public static void main(String args[]) {
	ReflectionTest rt = new ReflectionTest();
}

}
[/code]

O primeiro argumento que o set recebe eh o objeto que voce quer mudar algo argumento

Tipo

campoQueEuQuero.set(instancia, novoValorDoCampo);

Entao, soh mudei uma linha do seu codigo:

import java.lang.reflect.*; 
public class ReflectionTest { 
   public String testeStr = "Uma string"; 

   public ReflectionTest () { 
      init(); 
   } 

   protected void init() { 
      try { 
         Class cls = Class.forName( getClass().getName().toString() ); 
          
         Field field = cls.getField( "testeStr" ); 
         String str = new String(); 

         ///////////////////////////////
         // olha o THIS aqui  
         field.set( this, "String modificada"); 

        System.out.println( testeStr ); 
      } 
      catch (Throwable e) { 
         System.err.println(e); 
      } 

   } 

   public static void main(String args[]) { 
      ReflectionTest rt = new ReflectionTest(); 
   } 
} 

para fazer o Reflection de uma classe, ela tem que ter o construtor default.

[]s.

para falar a verdade não,
o constructor default só facilita caso você queira instanciar a classe por reflection, mas é possivel listar os construtores, depois os parametros do mesmo e instancia-la passando um array de Object como parametro paa suprir os parametros necessários :slight_smile:

Não pude ler o artigo e não comentar nada.
Reflection é um negócio muito legal.
Estou desenvolvendo uma arquitetura para geração de IHC baseada em três coisas legais do Java: Interfaces, carregamento dinâmico de classes e reflection.
Isso permite que eu tenha um frame (JFrame) de edição de dados de beans totalmente flexível. Este frame é instanciado em tempo de execução e ligado (via interface) a um fragmento de código genérico. Esse código, utilizando reflexão, atribui os valores corretos armazenados no bean para cada controle de tela. Essa atribuição usa reflexão (avançada eu diria), pois meu frame (e meus beans) podem ter propriedades privadas e também herdadas de classes superiores. Tudo isso é “aberto” pela reflexão e montado dinâmicamente para o usuário. O programador não faz nada.
Lento, talvez? Acho que não, fiz alguns testes iniciais e não tem diferença alguma. Usei o Log4J para testar a velocidade e a diferença de tempo ficou tão pequena (milésimos) de segundo que pode ser ignorada.

Finalmente, outra aplicação da reflexão é um esquema de gerenciamento de aplicações (vou ver se monto um artigo). Nesse esquema, o programador esqueçe coisas como “If usuario = X { controleY.setEnable(false)…}” O gerenciador se encarrega de fazer isso via reflexão e, pasmem, é muito rápido.

Bom, já falei demais. A dica é: usem e abusem de reflexão, não tenham medo, somente validem seu código muito bem.

Até,

Olá…
Sou novo no fórum e comecei a programar em java a pouco tempo.
Basicamente meu problema é o seguinte:
Suponha que criei uma aplicação que contém diversos pacotes.
Eu gostaria de obter a lista das classes que pertencem a um pacote específico (pacotex).
Por exemplo, se eu tiver um pacote de acoes e quero criar uma ação que lista todas as ações possíveis.
Sem saber em que diretório estão estas ações eu não consigo descobrir quais são todas as ações.
Alguém poderia me ajudar?
Tentei entender a documentação referente a Reflection e ClassLoader mas as APIs originais não me ajudaram muito. Quanto ao tutorial do GUJ, ele não me esclareceu muita coisa.

Boa tarde à todos.

Sei que já faz anos que foram postadas este artigo e comentários…
Mas a verdade é que os assuntos nunca ficarão velhos, já que JAVA ainda está fervendo.
Então, estou começando agora neste mundo de Reflection, Serializable, etc.

Com relação à duvida que o pessoal teve com um programinha, é o seguinte.

Este artigo foi uma tradução do que esta no site da SUN. Depois de algumas pesquisas, conclui que o programa correto é abaixo, pois houve uma falha do tradutor ter esquecido de mudar algumas coisas…

Segue abaixo o correto e funcionando…

import java.lang.reflect.*;

public class AlteraValor {

	public double d;
	
	public  static void main( String[] args ) {
		
		try {
			Class cls = Class.forName( "AlteraValor" );
		
			// localiza atributo da classe
			Field fld = cls.getField( "d" );
			
			// instancia um objeto da classe
			AlteraValor f2obj = new AlteraValor();
			System.out.println( "d = " + f2obj.d );
			
			// seta novo valor ao atributo utilizado
			fld.setDouble( f2obj, 12.34 );
			System.out.println( "d = " + f2obj.d );
			
		}	// fim TRY
		catch( Throwable e ) {
			System.err.println( e );
		}
	}	// fim do mpetodo MAIN

} // fim da classe AlteraValor

Abraços!!

Olha, eu li o tutorial, algumas publicações, mas naõ achei o que eu preciso.

Eu preciso saber uma forma de descobrir o tipo do parametro de um método de forma dinâmica. Como eu faço isso?

Vou dar um exemplo prático, para colocar dados de um ResultSet em um Benas. Daí eu preciso saber se a classe recebe um Int, umDouble ou uma String, para eu possa capturar os dados do ResultSet com o seu getInt, getDouble, GetString.

Como eu faço isso?

Já achei!! :slight_smile:

Para ficar registrado:

method.getParameterTypes()

Uma observação:

O framework SwingBean utiliza reflaction para fazer isto e muito mais, ainda suportando a parte de tabelas, validação de dados e etc… Vale a pena dar uma olhada, pois ele agiliza bastante o desenvolvimento:

http://swingbean.sourceforge.net

Bem,comecei a programar em Java a pouco tempo e estou precisando de ajuda para um trabalho. Eu tenho que criar um web service que faça uma busca através do tipo de dado de parametros de um método ou através do tipo de dado que determinado método retorna. :roll:

Estou usando o axis como servidor Wsdl mas a minha dúvida é como faço pra ler determinado método…já criei um cliente em java e tudo só falta a parte de programação… :frowning:

Desde já agradeço a ajuda

Brunno

Galera notei no tutorial que é possivel setar valores, e no caso de pegar o valor do atributo ?
Tipo preciso pegar o valor de um atributo e setar em um outro de outra classe.
Quero montar um Form Dinamico através do meu TO.

iuhyui

Paulo Silveira… fiz exatamente o que vc explicou neste trecho de codigo:


O primeiro argumento que o set recebe eh o objeto que voce quer mudar algo argumento

Tipo

campoQueEuQuero.set(instancia, novoValorDoCampo);

Entao, soh mudei uma linha do seu codigo:

Code:

import java.lang.reflect.*;
public class ReflectionTest {
public String testeStr = “Uma string”;

public ReflectionTest () { 
   init(); 
} 

protected void init() { 
   try { 
      Class cls = Class.forName( getClass().getName().toString() ); 
       
      Field field = cls.getField( "testeStr" ); 
      String str = new String(); 

      ///////////////////////////////
      // olha o THIS aqui  
      field.set( this, "String modificada"); 

     System.out.println( testeStr ); 
   } 
   catch (Throwable e) { 
      System.err.println(e); 
   } 

} 

public static void main(String args[]) { 
   ReflectionTest rt = new ReflectionTest(); 
} 

}


fiz isso pra setar meu objeto… so que agora estou com uma duvida seguinte: veja meu codigo…

	// carregando o collection
	if(rs.next()){
		array = new ArrayList<Object>();			
		//Object cls = null;
		do{				
			// Percorre os campos com os atributos de Pessoa.
			for (Field field : fields) {
				field.setAccessible(true);
				// verifica se é uma Annotation Coluna
	     			if (field.isAnnotationPresent(Coluna.class)) {
					// 'Acessando' a anotação
					Coluna coluna =  
                                                   field.getAnnotation(Coluna.class);	
					// invocando o método
					[b]field.set(o, rs.getObject(coluna.nome()));	[/b]					
					System.out.println(o.toString());
					}
			      }
					[b]array.add(o);	[/b]			
	     		} while(rs.next());
		}

no momento que adiciono o array com o objeto “o”, ele muda o valor do objeto inserido anteriormente… ou seja, se o “rs” possuir 10 linhas, vou ter um array com 10 objetos iguais com os valores do ultimo objeto inserido… eu entendo que é por causa da referencia deste objeto, pois a referencia é sempre a mesma com valores atualizados pra cada linha do
“rs” e por isso ele sempre muda os valores… mas teria outro jeito de fazer isso para manter meus objetos de acordo com cada linha do “rs”??? ja consegui fazendo assim: array.add(o.toString()); mas ai ele popula o array com strings e eu precisava que esse array fosse populado com objetos… pois ele é o retorno do meu metodo e onde vou usa-lo preciso dos objetos!

Para pegar o valor do atributo utilize:

seuField.get(suaClasse);

ia ler o tutorial mais está dando erro 404 quando tento acessar

Usando flection teria como eu criar uma lista
dos atributos da classe? e depois setar valores a eles?

Teria sim. Pode fazer de diversas formas. Abaixo segue o exemplo da “idéia” de como fazer.



//Para percorrer os atributos de uma determinada classe
for (java.lang.reflect.Field field : suaClasse.getClass().getDeclaredFields()) {
         //Caso for private, modifica o acesso permitindo setar valores
         field.setAccessible(true);
         //Seta os valores
         field.set(suaClasse,field.getType().cast("Valor novo"));
			
}