2013-07-03 4 views
3

Как и для this question, мне нужно получить доступ ко всем частным полям одного экземпляра POJO. Разница в том, что я не знаю конкретных имен полей (ях), которые я хочу раньше времени.Список всех частных полей объекта Java?

Например, если мой POJO является:

public class Widget { 
    private java.lang.String fizz; 
    private java.lang.Boolean buzz; 
    private com.me.myapp.Foo foo; 
} 

Я ищу какой-то способ проверки на Widget экземпляре (или сам класс) и вижу, что у него есть эти 3 поле/типов, не зная, их имена/типы раньше времени.

Возможно ли это? Если да, то как? Если нет, то почему?

Update:

System.out.println("classToInspect = " + classToInspect.getName() + ", and fields are:\n"); 
for(Field f : allFields) 
    System.out.println(f.getType()); 

Печать:

classToInspect = com.myorg.myapp.LoggerConfig, and fields are: 

int 
int 
int 
class java.lang.reflect.Constructor 
class java.lang.Class 
class java.lang.String 
class java.security.ProtectionDomain 
boolean 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
class java.lang.ref.SoftReference 
int 
int 
class sun.reflect.generics.repository.ClassRepository 
long 
class [Ljava.io.ObjectStreamField; 
class sun.reflect.ReflectionFactory 
boolean 
class [Ljava.lang.Object; 
interface java.util.Map 
class [Ljava.lang.annotation.Annotation; 
interface java.util.Map 
interface java.util.Map 
class sun.reflect.annotation.AnnotationType 

Пожалуйста, обратите внимание: ни одно из этих полей поля/свойства/члены моего фактического LoggerConfig класса; они должны быть обеспечены/добавлено через отражение или часть Object суперкласса ...

+0

Не этот вопрос решить проблему? –

+0

Отметьте этот вопрос: http://stackoverflow.com/questions/1555658/is-it-possible-in-java-to-access-private-fields-via-reflection –

+0

И почему вы просто хотите получить к ним доступ? – fge

ответ

4

Вы можете использовать метод getDeclaredFields из Class класса, чтобы получить все поля, объявленные в классе независимо от его модификатора. Использование метода getDeclaredFields предоставит вам массив из Field, который затем вы можете перебрать, и вызовите метод getType, чтобы получить типы полей. Следующий код демонстрирует тот же:

class TestClass 
{ 
    private String x; 
    private int y; 
    private boolean z; 
} 
public class Test 
{ 
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException 
    { 
     Class clazz = TestClass.class; 
     Field[] fields = clazz.getDeclaredFields(); 
     for (Field field : fields) 
     { 
      System.out.println("fieldName: "+field.getName()+", fieldType: "+field.getType()); 
     } 
    } 
} 

Приведенный выше код выхода:

fieldName: x, fieldType: class java.lang.String 
fieldName: y, fieldType: int 
fieldName: z, fieldType: boolean 
5

использование ниже список всех частных полей

List<Field> privateFields = new ArrayList<>(); 
    Field[] allFields = SomeClass.class.getDeclaredFields(); 
    for (Field field : allFields) { 
     if (Modifier.isPrivate(field.getModifiers())) { 
      privateFields.add(field); 
      System.out.format("type is", field.getType()); 
     } 
    } 
+0

Спасибо @M Sach - 'getDeclaredFields()' возвращает все поля, но когда я распечатываю их тип через getClass(). GetName() ', типы полей печатаются как' java.lang.reflect.Field'. ** Как я могу получить базовый тип класса самого поля? ** Еще раз спасибо! –

+0

@TicketMonster try 'field.getType()' – Esailija

+0

@TicketMonster вы вызываете этот метод в самом классе 'Field', поэтому вы получаете данные, относящиеся к' Field'. Чтобы получить тип, используйте 'getTipe()'. – Gamb

4

FYI, ответ M Сакса хорошо работает для одного класса, но будет не дают private полей в базовом классе. Я выполнил следующее, которое даст всем полям иерархию классов. Это в сочетании с этим ответом было бы более универсальным.

/** 
* Retrieves all fields (all access levels) from all classes up the class 
* hierarchy starting with {@code startClass} stopping with and not 
* including {@code exclusiveParent}. 
* 
* Generally {@code Object.class} should be passed as 
* {@code exclusiveParent}. 
* 
* @param startClass 
*   the class whose fields should be retrieved 
* @param exclusiveParent 
*   if not null, the base class of startClass whose fields should 
*   not be retrieved. 
* @return 
*/ 
public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass, @Nullable Class<?> exclusiveParent) { 
    List<Field> currentClassFields = newArrayList(startClass.getDeclaredFields()); 
    Class<?> parentClass = startClass.getSuperclass(); 

    if (parentClass != null && (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) { 
     List<Field> parentClassFields = (List<Field>) getFieldsUpTo(parentClass, exclusiveParent); 
     currentClassFields.addAll(parentClassFields); 
    } 

    return currentClassFields; 
} 
+0

Спасибо @John B (+1) - см. Мое обновление - 'Поле # getType()' не работает! –

+0

Вы должны передать 'Object.class' в качестве второго аргумента моего метода, чтобы предотвратить включение полей в« Object »из списка полей. –

+0

Это должен быть принятый ответ; также я хотел бы указать, что для нестатических внутренних классов результаты не включают в себя поле, относящееся к экземпляру окружающего класса? Точно так же, как у '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '', '', как свой первый аргумент. – Andy

1

Использование отражения:

Widget widget = new Widget(); 
java.lang.reflect.Field[] fields = widget.getClass().getDeclaredFields(); 

Вы можете использовать field.isAccessible(), чтобы проверить его доступность или даже изменить его на публике с field.setAccessible(true);

Смежные вопросы