Pegar o nome da variavel via Reflection

Seguinte,

Como eu faço pra pegar o nome da variavel por reflection, por exemplo:

public String montaMeuNome(String primeiroNome, String segundoNome){ return primeiroNome + " " + segundoNome; }

Como eu faço pra saber que o primeiro argumento desse método tem o nome “primeiroNome” e o segundo argumento é o “segundoNome”?
Sei que em uma versão dessas mais nova do Java (Java 6 se não me engano) já existe esta possibilidade…

E ai? Alguem sabe?
PS: Se não me engano o Louds ou o Thingol falou/falaram disso aqui uma vez mas eu não achei por nada…

Vixi sera que tem como? da pra pegar o tipo do argumento, mas o nome não tenho ideia, me diz pra que tu precisa do nome da variavel?

Bem, digamos que eu um determinado momento da minha chamada a um método via reflection, eu precise escolhe o atributo pelo nome…
Imagine que eu tenha, em um contexto qualquer, 3 strings em uma lista. No método de exemplo no inicio do Post, qual String vc iria passar para o método?!? Sacou?!?
Pra matar mais ainda a sua curiosodade, trata-se de um framework meio MVC, meio RESTful, pra atender a demanda de um cliente…

Bom, não entendi mto bem seu exemplo e nem sei se tem como fazer isso, hehe (até pq a máquina virtual guarda a referência na memória e não o nome da variável)…
Mas vc pode ter alguém que mapeia isso pra vc. O VRaptor, por exemplo, usa o nome do parâmetro do request pra isso: um campo no formulário de name “pessoa.nome” diz pro VRaptor chamar via reflection setNome() da classe Pessoa…

Rodrigo tente fazer isto criando Annotation, por exemplo:
-Primeiro crie sua Annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER, 
          ElementType.METHOD, 
          ElementType.CONSTRUCTOR})
public @interface Parameter {
	String value();
}

-Segundo declare em cada parâmetro do seu método essa Annotation passando o nome de cada atributo nos valores, o exemplo mostra como ficaria seu método e um exemplo de como pegar os nomes utilizando Reflection com sua Annotation:

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class Teste {

	public String montaMeuNome(@Parameter("primeiroNome")
	String primeiroNome, @Parameter("segundoNome")
	String segundoNome) {
		return "";
	}

	public static void main(String args[]) {
		Teste teste = new Teste();
		try {
			Method metodo = teste.getClass().getMethod("montaMeuNome",
					String.class, String.class);
			Annotation[][] ann = metodo.getParameterAnnotations();
			for (int i = 0; i < ann.length; i++) {
				Annotation[] an = ann[i];
				for (int j = 0; j < an.length; j++) {
					if(an[j] instanceof Parameter) {
						String name = ((Parameter)an[j]).value();
						System.out.println(name);
					}
				}
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Neste código como resultado ele imprime:

primeiroNome
segundoNome

Espero ter ajudado…

[]'s

Poxa amigo, eu costumo usar Reflection e inclusive provavelmente foi pra mim que o Thingol respondeu o tal post que vc diz estar procurando e não ter achado por nada.

Mas o problema é que eu realmente não consegui entender o que vc quer… pode me explicar melhor?! :oops:

É, acho que eu não to me expressando direto por mais que o exemplo seja simples… vamos para a vida real…
Imagine que vc irá programar agora uma classe “tipo Controller” para a sua aplicação e nela vc precisa criar o método processaLogin, conforme assinatura abaixo.

private void processaLogin(String username, String password)

Agora, imagine que vc tem uma “bolsa de objetos”, onde vc precisa pegar dois objetos do tipo String com esses nomes, para fazer a chamada do método processaLogin passando os argumentos corretos… sacou?
E não adianta usar anotações ou injetar no momento de criação da classe… eu preciso pegar o método, saber o nome dos argumentos que ele recebe e receber o retorno com o nome do argumento tb…

Vc quer retornar o nome dos parâmetros do seu método, não é isso ?
Usando Annotation é uma solução prática, o exemplo não está injetado durante a criação da Classe, vc vai simplesmente declarar a Annotation em cada um dos parâmetros do seu método passando o nome deles, e vai recupera-las usando Reflection.

Ou realmente não estamos entendendo.

Acho que não tem como recuperar o nome do parâmetro utilizando apenas Reflection, com versões anteriores ao Java 6.

[]'s

Cara não sei se tem como fazer isto que vc quer não… mas se não tiver uma outra solução é vc mapear a classe e o metodo e os argumentos exemplo:


 &lt;classe name="MinhaClasse" src="org.minhaclase.MinhaClasse" &gt;
     &lt;metodo name="processaLogin" nomeParametros="username, senha"/&gt;
 &lt;/classe&gt;

da mais trabalho pro cara criar esses xmls o tempo todo que precisar desta funcionalidade mas é um quebra-galho neste sentido…

Hm, você pode também enviar os parâmetros na ordem esperada.

Ooou não usar parâmetros nos métodos. Cada Action tem um método “execute”, e o controller apenas seta os parâmetros dessa classe.

Nenhum dos métodos de java.lang.reflect.Method trás o nome dos parâmetros.

De fato, a máquina virtual não conhece os nomes dos parâmetros, apenas os seus tipos. Os nomes dos parâmetros são perdidos durante a compilação, tanto que se você abrir o .class gerado em um editor de textos ou em editor hexadecimal, os nomes dos parâmetros não estarão lá!

Então, você vai ter que resolver de outra forma.

[quote=lcegatti]Usando Annotation é uma solução prática, o exemplo não está injetado durante a criação da Classe, vc vai simplesmente declarar a Annotation em cada um dos parâmetros do seu método passando o nome deles, e vai recupera-las usando Reflection.
[/quote]
Vc entendeu perfeitamente… só que eu estava pensando em uma solução que deixa o desenvolvedor livre pra fazer isso… ou não depender de nada meu, sacou? Eu não queria nem anotação, mas faz-se necessário…
Vou pensar um pouco mais nessa anotação…

[quote=luistiagos]Cara não sei se tem como fazer isto que vc quer não… mas se não tiver uma outra solução é vc mapear a classe e o metodo e os argumentos exemplo:


 &lt;classe name="MinhaClasse" src="org.minhaclase.MinhaClasse" &gt;
     &lt;metodo name="processaLogin" nomeParametros="username, senha"/&gt;
 &lt;/classe&gt;

da mais trabalho pro cara criar esses xmls o tempo todo que precisar desta funcionalidade mas é um quebra-galho neste sentido…[/quote]
É… mas entre anotação e xml, fico a anotação…

[quote=LIPE]Hm, você pode também enviar os parâmetros na ordem esperada.
Ooou não usar parâmetros nos métodos. Cada Action tem um método “execute”, e o controller apenas seta os parâmetros dessa classe.[/quote]
ID nos atributos?!? com isso eu usaria o Spring ou o próprio BeanUtils…

[quote=victorwss]Nenhum dos métodos de java.lang.reflect.Method trás o nome dos parâmetros.

De fato, a máquina virtual não conhece os nomes dos parâmetros, apenas os seus tipos. Os nomes dos parâmetros são perdidos durante a compilação, tanto que se você abrir o .class gerado em um editor de textos ou em editor hexadecimal, os nomes dos parâmetros não estarão lá!

Então, você vai ter que resolver de outra forma.[/quote]
Disso eu sei… mas eu me lembro que alguem aqui do forum comentou sobre em uma versão do Java (6 ou 7) iria existir esta possibilidade…

De fato:

  • O que o VictorWSS tinha dito está certo;
  • Os nomes dos parâmetros estão presentes nos arquivos .class se eles tiverem sido compilados com informação de debugging (isso porque eles são armazenados mais ou menos como se fossem variáveis locais, e como você deve saber, os nomes de variáveis locais são guardados apenas se a informação de debugging estiver presente no .class);
  • Eles não são recuperáveis via reflection;
  • Antes do lançamento do Java 6.0 o pessoal da Sun tinha prometido que essa informação iria ficar disponível via reflection, porque ela é importante para expor métodos de classes normais como web services. Só que isso aparentemente acabou não sendo feito. Não sei se existe uma maneira “torta” de fazer isso.
  • Não sei se alguma versão mais recente do ASM ( http://asm.objectweb.org ) permite analisar um arquivo .class de forma que essa informação possa ser obtida. É questão de dar uma olhada.

Nossa, agora eu acho que entedi a questão… vc quer pegar o nome dos parâmetros de um método que vc acessa por reflection, né?

Puxa, realmente não sei como fazer isso… eu acho que o post q rolou no guj q vc fala é esse aqui http://www.guj.com.br/posts/list/77566.java

Foi uma questão minha, mas era pra pegar o nome de um componente, não de um parâmetro…

Sei q esse topico eh meio antigo, mesmo assim seguem meus .02 cents pois precisei disso ha pouco, e tive q correr atras…

Se sua classe foi compilada com os simbolos de debug, o .class possui internamente o q se chama de LocalVariableTable, acessivel somente(pelo menos por enquanto) por instrumentacao de codigo, via ASM, Javassist, etc…

Se vc precisar disso, olhe o utilitario LocalVariableTableParameterNameDiscoverer.getParameterNames do Spring. Cabe lembrar q eh necessario ler os javadocs dessa classe, pois existem dicas de otimizacao de uso dessa classe.