Reflection

Olá pessoal!

Eu sei acessar por reflection declarações da minha classe (métodos, variáveis, etc…)

Mas tenho um caso aqui em que quero acessar variáveis que estão dentro de um método. Ai dá erro dizendo que não encontrou a variável. Vejam o erro:

java.lang.NoSuchFieldException: pHistimp1

Tudo acontece dentro do meu método geracaoDemonstrativoLucroPrejuizo(), as variáveis estão declaradas ai dentro e eu tb estou executando o comando reflection ai dentro.

Estou tentando assim:

[code]int vCodigo = 0;

try {
vCodigo = (Integer)this.getClass().getField(“pHistimp1”).get(this);
} catch (Exception e) {
e.printStackTrace();
}
[/code]
Não funciona, dá o erro que eu já falei.
Então tentei especificar o método em que eu estou, tentei da seguinte forma:

[code]int vCodigo = 0;

try {
Method metodo = this.getClass().getDeclaredMethod(“geracaoDemonstrativoLucroPrejuizo”,new Class[] {});

vCodigo  = (Integer)metodo.getClass().getField("pHistimp1").get(metodo);

} catch (Exception e) {
e.printStackTrace();
}
[/code]
Tb não funciona, continua dando o mesmo erro.

Antes que perguntem, sim, essa variável existe e está acessível nesse momento, já conferi isso.

Alguém sabe como faço pra que ele procure a declaração da variável dentro do meu método?

Grata,
Renata

Uma variável local não pode ser obtida ou acessada via reflection, até porque ela pode ser “optimized out” (ou seja, removida ou transformada devido à otimização).
É uma variável local mesmo que você está tentando obter?

Sim, é uma variável local.

Certeza de que não pode?! :cry:

“Alguma forma” com certeza existe! Afinal qdo fazemos o debug da aplicação, é possível ler/alterar variaveis dentro de um método… correto?
Mas tbm desconheço esse recurso seja na reflection ou GCLib… com certeza isso demanda uma boa pesquisa!

Cabe a vc verificar a viabilidade disso…

[]s

o Debug é feito através da pilha de chamadas

se houver algum jeito de pegar variaveis dentro de um método, eu desconheço

Reflection só tem acesso a váriaveis declaradas como public.

Para ter acesso a valores use os métodos convencionais get e set.

:wink:

um exemplo de bandeja:

 entity = new Pessoa();
 Method [] metodos = entity.getClass().getMethods();
        
        for(int i =0; i < metodos.length; i++){
            Method m = metodos[i];
            if(!m.getName().contains("get") || m.getName().contains("getClass")){
                continue;
            }
            Method method;
            try {
                method = entity.getClass().getDeclaredMethod(m.getName());
                Object value = method.invoke(entity);
                if(value != null){
                    System.out.ptintln(value);    
                }
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

Infelizmente o exemplo “de bandeja” não me ajuda…rs…

As variáveis estão declaradas dentro do método, não dentro de uma classe. É um caso de variável local msm, parece que não vai dar.

Bom, farei de outra forma aqui, vlw ai pela ajuda, fiquei na curiosidade de entender pq meu Reflection não estava funcionando, agora sei.

Grata,
Renata

Infelizmente, variáveis locais e parâmetros não podem ser acessados corretamente via reflection.

Quanto às primeiras eu digo que é realmente complicado obter a variável correta “por nome”, já que escopos são difíceis de especificar corretamente, e envolveriam a colaboração do compilador.

Quanto aos segundos, eu acho que é uma falha da API de reflection.

Haviam prometido que iriam incluir parâmetros no reflection (por exemplo, listar os nomes dos parâmetros de um método via reflection), mas por enquanto você só consegue saber os tipos de cada parâmetro de um método, mas não seus nomes. Isso provavelmente não será mudado no Java 7, conforme você pode ver em: http://download.java.net/jdk7/docs/api/java/lang/reflect/Method.html

Voce pode acessar campos com qualquer declaração de privacidade mas apenas as variaveis globais.

Voce pode ter o acesso aos métodos com o Javaassist, mas não é algo simples.

Se divirta XD

Renata (desculpe a curiosidade) mas eu não vejo uma situação em que é preciso usar reflections dentro de um método com uma varíavel de método… :confused:

[quote=Giulliano]Renata (desculpe a curiosidade) mas eu não vejo uma situação em que é preciso usar reflections dentro de um método com uma varíavel de método… :/[/quote]Leu meu pensamento :smiley:

Acho que ela quer criar uma rotina que pode listar ou modificar uma variável local ou de instância, passando apenas o nome. Só que isso é um pouco inviável no caso de uma variável local, até por causa dos problemas de escopo.

Então eu acho q na nossa área, sempre podemos nos surpreender a cada dia devido ao dinamismo dela, é isto que torna o desenvolvimento interessante.

Vou pesquisar algo pra vc e já posto…
Abraços.

Não é possível recuperar as variáveis em um método, por causa do escopo delas. O tempo de vida é muito curto, e provavelmente, esse erro que você apresentou, ocorre devido ao fato de que essas variáveis não existem mais.

Mais simples do que imaginam…

Tenho uma situação idiota aqui, que ocorre dentro de um método, em que o nome de algumas variáveis são bem parecidos, suponhamos por ex que seja assim: valor1, valor2, valor3,… valor5 e cod1, cod2,… cod6

O processamento que tenho que fazer para elas será sempre o mesmo, então eu fiz um for básico, de 1 a 6 (seguindo meu exemplo acima de nomes de variáveis), onde eu fazia o mesmo processamento pra todas as vars. Porém fui desbancada pelo fato da Reflection não pegar variáveis.

Eu já faço isso em outros casos, casos em que por ex, na tela tenho caixas de texto com nomes parecidos, etc… mas ai são variáveis públicas.

Bom, satisfeita a curiosidade do povo. :wink:

Tenho a impressão que você está sofrendo sem necessidade… :slight_smile:

Eu teria feito dessa maneira:

Object[] codigos = {cod1, cod2, cod3, cod4, cod5, cod6}
Object[] valores = {valor1, valor2, valor3, valor4, valor5, valor6}
// Coloquei como Object porque não sei o tipo
for (int i = 0; i < codigos.length; i++) {
     //Processa
}

Tá certo que vai precisar digitar o nome de cada variável na declaração do array, mas nem se compara a repetir todo o código.
E também tem vantagens sobre a solução com Reflection: o código fica mais “limpo” e um pouco mais seguro contra erros pois é verificado na compilação.

[quote=gomesrod]Tenho a impressão que você está sofrendo sem necessidade… :slight_smile:

Eu teria feito dessa maneira:

Object[] codigos = {cod1, cod2, cod3, cod4, cod5, cod6}
Object[] valores = {valor1, valor2, valor3, valor4, valor5, valor6}
// Coloquei como Object porque não sei o tipo
for (int i = 0; i < codigos.length; i++) {
     //Processa
}

Tá certo que vai precisar digitar o nome de cada variável na declaração do array, mas nem se compara a repetir todo o código.
E também tem vantagens sobre a solução com Reflection: o código fica mais “limpo” e um pouco mais seguro contra erros pois é verificado na compilação.[/quote]

Não, não estou sofrendo… eu já resolvi, como eu falei num post dias atrás. Alias, fiz algo bem parecido com o que vc fez.

Como eu falei no outro post, eu só tentei usar via Reflection, não funcionou e eu queria entender pq não estava funcionando. Agora eu aprendi que é pq Reflection não acessa vars privadas. Foi para entender o motivo de não funcionar… eu segui fazendo de outra forma e pronto. :wink:

Bom dia,

Se as varíaveis locais do método são de mesmo typo, talvez utilizare um array[] o equivalente e depois utilizar o FOR :
O processamento que fazer para elas será sempre o mesmo ?

gomesrod,  tivemos a mesma idea mas o tempo para a minha messagem chegar de Paris au Brasil você fez o post antes de mim :-)

Abraços

Sim sim… você já disse que tinha achado uma solução, só estava mesmo metendo o nariz onde não fui chamado :slight_smile:

Mas já que estamos falando no assunto, tem uma pequena regra que costumo seguir: Usar Reflection é para frameworks e classes de infraestrutura; para as classes “normais” (negócio, telas, etc) sempre existem alternativas mais simples e seguras.

[quote=JxtaNode]gomesrod, tivemos a mesma idea mas o tempo para a minha messagem chegar de Paris au Brasil você fez o post antes de mim [/quote] É, ouvi falar que os aeroportos estão um caos :frowning: