Obtendo valor de propriedade / campo público estático final de uma classe em Java por meio de reflexão

103

Digamos que eu tenha uma aula:

public class R {
    public static final int _1st = 0x334455;
}

Como posso obter o valor de "_1st" via reflexão?

Viet
fonte
R._1stnão funcionou? Se você está falando sobre desenvolvimento Android, acho que a Raula está sempre lá ...
Matthieu
@Matthieu Eu também achava, até hoje quando tive que fazer exatamente isso, mas só com a BRclasse.
Sevastyan Savanyuk

Respostas:

132

Primeiro, recupere a propriedade do campo da classe, então você pode recuperar o valor. Se você souber o tipo, poderá usar um dos métodos get com null (apenas para campos estáticos; na verdade, com um campo estático o argumento passado para o método get é totalmente ignorado). Caso contrário, você pode usar getType e escrever uma opção apropriada conforme abaixo:

Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
    System.out.println(f.getInt(null));
}else if(t == double.class){
    System.out.println(f.getDouble(null));
}...
M. Jessup
fonte
obrigado. Eu tentei, mas não funcionou. A exceção é lançada na operação f.getInt (null). Eu percebi, mas como pode haver uma exceção?
Viet
1
Que tipo de exceção você recebeu?
M. Jessup
Olá, o Exception e.getMessage () retorna o nome do campo, que é "_1st" e nada mais.
Viet
1
Mas qual é o tipo de exceção? (ou seja, NullPointerException, SecurityException, ...)
M. Jessup,
2
Como é que a documentação nunca menciona que getInt()ignora o argumento passado? Passei horas tentando fazer com que a instância da classe passasse ali.
Sevastyan Savanyuk
70
 R.class.getField("_1st").get(null);

O tratamento de exceções é deixado como um exercício para o leitor.

Basicamente, você obtém o campo como qualquer outro por meio de reflexão, mas ao chamar o método get, você passa um nulo, pois não há instância para agir.

Isso funciona para todos os campos estáticos, independentemente de serem finais. Se o campo não for público, você precisa chamá setAccessible(true)-lo primeiro e, claro, o SecurityManager deve permitir tudo isso.

Yishai
fonte
Deixa comigo. A aula de que eu precisava era, na verdade, R.id. Obrigado pela ajuda!
Viet
1

Eu estava seguindo a mesma rota (olhando através da classe R gerada) e então tive a terrível sensação de que provavelmente era uma função da classe Recursos. Eu tinha razão.

Encontrou isto: Resources :: getIdentifier

Achei que isso pudesse economizar algum tempo. Embora digam que é desencorajado nos documentos, o que não é muito surpreendente.

Brian
fonte
Então você deduziu que era uma questão do Android. Deveria ter sido indicado nas tags ...
Matthieu
Não é uma questão Android, é uma questão de reflexão Java que usa um exemplo particular. As perguntas são marcadas com base em seu tópico.
Matthew leu