5

这个问题类似,我需要访问一个 POJO 实例的所有私有字段。不同之处在于我事先不知道我想要的字段的具体名称。

例如,如果我的 POJO 是:

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

我正在寻找某种方法来检查Widget实例(或类本身)并查看它具有这 3 个字段/类型,而无需提前知道它们的名称/类型。

这可能吗?如果是这样,怎么做?如果不是,为什么?

更新

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超类的一部分提供/添加......

4

4 回答 4

7

您可以使用类的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
于 2013-07-03T17:54:27.760 回答
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());
        }
    }
于 2013-07-03T15:05:50.000 回答
4

仅供参考,M Sach 的答案适用于单个类,但不会给出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;
}
于 2013-07-03T15:13:53.940 回答
1

使用反射:

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

您可以使用field.isAccessible()它来检查它的可访问性,甚至可以将其更改为公开field.setAccessible(true);

于 2013-07-03T15:13:54.970 回答