Usando o Java Reflection, é possível obter o nome de uma variável local? Por exemplo, se eu tiver isso:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
é possível implementar um método que pode encontrar os nomes dessas variáveis, assim:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
Edição: Esta pergunta é diferente de Existe uma maneira em Java para encontrar o nome da variável que foi passada para uma função? na medida em que faz mais puramente a pergunta sobre se alguém pode usar a reflexão para determinar o nome de uma variável local, enquanto a outra pergunta (incluindo a resposta aceita) está mais focada no teste de valores de variáveis.
java
reflection
David Koelle
fonte
fonte
Respostas:
No Java 8, algumas informações sobre o nome da variável local estão disponíveis através da reflexão. Veja a seção "Atualização" abaixo.
Informações completas geralmente são armazenadas em arquivos de classe. Uma otimização em tempo de compilação é removê-lo, economizando espaço (e oferecendo alguma ofuscação). No entanto, quando está presente, cada método possui um atributo de tabela de variável local que lista o tipo e o nome das variáveis locais e o intervalo de instruções em que estão no escopo.
Talvez uma biblioteca de engenharia de código de bytes como o ASM permita inspecionar essas informações em tempo de execução. O único lugar razoável em que posso pensar em precisar dessas informações é em uma ferramenta de desenvolvimento e, portanto, a engenharia de código de bytes provavelmente também será útil para outros fins.
Atualização: Suporte limitado a isso foi adicionado ao Java 8. Os nomes de parâmetros (uma classe especial de variável local) agora estão disponíveis via reflexão. Entre outras finalidades, isso pode ajudar a substituir as
@ParameterName
anotações usadas pelos contêineres de injeção de dependência.fonte
É não possível a todos. Os nomes de variáveis não são comunicados no Java (e também podem ser removidos devido a otimizações do compilador).
EDIT (relacionado aos comentários):
Se você se afastar da ideia de usá-lo como parâmetros de função, aqui está uma alternativa (que eu não usaria - veja abaixo):
Haverá problemas se
a == b, a == r, or b == r
ou houver outros campos com as mesmas referências.EDIT agora desnecessário, pois a pergunta foi esclarecida
fonte
( Editar: duas respostas anteriores removidas, uma por responder à pergunta como estava antes das edições e outra por estar, se não absolutamente errada, pelo menos próxima a ela. )
Se você compilar com informações de depuração em (
javac -g
), os nomes das variáveis locais serão mantidos no arquivo .class. Por exemplo, pegue esta classe simples:Após compilar com
javac -g:vars TestLocalVarNames.java
, os nomes das variáveis locais agora estão no arquivo .class.javap
O-l
sinalizador ("Número da linha de impressão e tabelas de variáveis locais") pode mostrá-los.javap -l -c TestLocalVarNames
mostra:A especificação da VM explica o que estamos vendo aqui:
§4.7.9 O
LocalVariableTable
atributo :Ele
LocalVariableTable
armazena os nomes e tipos das variáveis em cada slot, para que seja possível combiná-los com o bytecode. É assim que os depuradores podem fazer "Avaliar expressão".Como disse Erickson, no entanto, não há como acessar esta tabela através da reflexão normal. Se você ainda estiver determinado a fazer isso, acredito que a JPDA (Java Platform Debugger Architecture) ajudará (mas nunca a usei).
fonte
javac
coloca uma tabela de variável local na classe para cada método para ajudar na depuração. Use a-l
opção parajavap
ver a tabela de variáveis locais.javac -g:vars
para obtê-lo. (Eu venho tentando editar esta resposta para os últimos três horas, mas como eu disse a minha conexão de rede está com problemas, o que torna difícil para a pesquisa.)fonte
getDeclaredFields()
pode ser usado no caso de você deseja que os nomes de campo privada, bemVocê pode fazer assim:
fonte
Tudo o que você precisa fazer é criar uma matriz de campos e depois configurá-la para a classe que você deseja, como mostrado abaixo.
Por exemplo, se você fez
você receberia
fonte
atualize a resposta geral de @Marcel Jackwerth.
e trabalhando apenas com o atributo class, não trabalhando com a variável de método
fonte
veja este exemplo:
fonte