Não há suporte linguístico para fazer o que você está pedindo.
Você pode acessar reflexivamente os membros de um tipo em tempo de execução usando reflexão (por exemplo, com Class.getDeclaredFields()
para obter um array de Field
), mas dependendo do que você está tentando fazer, esta pode não ser a melhor solução.
Veja também
Perguntas relacionadas
Exemplo
Aqui está um exemplo simples para mostrar apenas parte do que a reflexão é capaz de fazer.
import java.lang.reflect.*;
public class DumpFields {
public static void main(String[] args) {
inspect(String.class);
}
static <T> void inspect(Class<T> klazz) {
Field[] fields = klazz.getDeclaredFields();
System.out.printf("%d fields:%n", fields.length);
for (Field field : fields) {
System.out.printf("%s %s %s%n",
Modifier.toString(field.getModifiers()),
field.getType().getSimpleName(),
field.getName()
);
}
}
}
O trecho acima usa reflexão para inspecionar todos os campos declarados de class String
; ele produz a seguinte saída:
7 fields:
private final char[] value
private final int offset
private final int count
private int hash
private static final long serialVersionUID
private static final ObjectStreamField[] serialPersistentFields
public static final Comparator CASE_INSENSITIVE_ORDER
Effective Java 2nd Edition, Item 53: Prefere interfaces para reflexão
Estes são trechos do livro:
Dado um Class
objeto, você pode obter Constructor
, Method
e Field
instâncias que representam os construtores, métodos e campos da classe. [Eles] permitem que você manipule reflexivamente suas contrapartes subjacentes . Esse poder, no entanto, tem um preço:
- Você perde todos os benefícios da verificação em tempo de compilação.
- O código necessário para realizar o acesso reflexivo é desajeitado e prolixo.
- O desempenho sofre.
Como regra, os objetos não devem ser acessados reflexivamente em aplicativos normais em tempo de execução.
Existem alguns aplicativos sofisticados que requerem reflexão. Os exemplos incluem [... omitido propositalmente ...] Se você tiver alguma dúvida se seu aplicativo se enquadra em uma dessas categorias, provavelmente não.
Field.get
você pode usar para ler os valores de um campo reflexivamente. Se forprivate
, talvez você consiga contornar isso comsetAccessible
. Sim, a reflexão é muito poderosa e permite que você faça coisas como inspecionarprivate
campos, sobrescreverfinal
campos, invocarprivate
construtores, etc. Se precisar de mais ajuda com o aspecto do design, você provavelmente deve escrever uma nova pergunta com muito mais informações. Talvez você não precise desses muitos atributos em primeiro lugar (por exemplo, useenum
ouList
, etc).static void inspect(Class<?> klazz)
Acessar os campos diretamente não é um estilo muito bom em java. Eu sugeriria criar métodos getter e setter para os campos de seu bean e então usar as classes Introspector e BeanInfo do pacote java.beans.
MyBean bean = new MyBean(); BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class); for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) { String propertyName = propertyDesc.getName(); Object value = propertyDesc.getReadMethod().invoke(bean); }
fonte
propertyDesc.getReadMethod().getDeclaringClass() != Object.class
ou especificar uma classe para interromper a análise como o segundo parâmetrogetBeanInfo(MyBean.class, Object.class)
.Embora eu concorde com a resposta de Jörn se sua classe está em conformidade com a especificação JavaBeabs, aqui está uma boa alternativa se não estiver e você usar Spring.
Spring tem uma classe chamada ReflectionUtils que oferece algumas funcionalidades muito poderosas, incluindo doWithFields (classe, retorno de chamada) , um método de estilo de visitante que permite iterar sobre os campos de uma classe usando um objeto de retorno de chamada como este:
public void analyze(Object obj){ ReflectionUtils.doWithFields(obj.getClass(), field -> { System.out.println("Field name: " + field.getName()); field.setAccessible(true); System.out.println("Field value: "+ field.get(obj)); }); }
Mas aqui está um aviso: a classe é rotulada como "apenas para uso interno", o que é uma pena se você me perguntar
fonte
Maneira simples de iterar nos campos da classe e obter valores do objeto:
Class<?> c = obj.getClass(); Field[] fields = c.getDeclaredFields(); Map<String, Object> temp = new HashMap<String, Object>(); for( Field field : fields ){ try { temp.put(field.getName().toString(), field.get(obj)); } catch (IllegalArgumentException e1) { } catch (IllegalAccessException e1) { } }
fonte
Java tem Reflection (java.reflection. *), Mas eu sugiro olhar em uma biblioteca como o Apache Beanutils, isso tornará o processo muito menos complicado do que usar reflexão diretamente.
fonte
Aqui está uma solução que classifica as propriedades em ordem alfabética e as imprime todas junto com seus valores:
public void logProperties() throws IllegalArgumentException, IllegalAccessException { Class<?> aClass = this.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); Map<String, String> logEntries = new HashMap<>(); for (Field field : declaredFields) { field.setAccessible(true); Object[] arguments = new Object[]{ field.getName(), field.getType().getSimpleName(), String.valueOf(field.get(this)) }; String template = "- Property: {0} (Type: {1}, Value: {2})"; String logMessage = System.getProperty("line.separator") + MessageFormat.format(template, arguments); logEntries.put(field.getName(), logMessage); } SortedSet<String> sortedLog = new TreeSet<>(logEntries.keySet()); StringBuilder sb = new StringBuilder("Class properties:"); Iterator<String> it = sortedLog.iterator(); while (it.hasNext()) { String key = it.next(); sb.append(logEntries.get(key)); } System.out.println(sb.toString()); }
fonte