在Java中使用反射获取成员变量值的陷阱

在Java中使用反射获取成员变量值的陷阱,java,reflection,Java,Reflection,我有一个抽象类,如下所示。我想得到所有成员变量的值 public abstract class PARAMS { public static final String NAME1 = "VAL1"; public static final String NAME2 = "VAL2"; public static final String NAME3 = "VAL3"; } 使用反射检索这些值,如下所示 Field[] fields = PARAMS.class.getF

我有一个抽象类,如下所示。我想得到所有成员变量的值

public abstract class PARAMS {
    public static final String NAME1 = "VAL1";
    public static final String NAME2 = "VAL2";
    public static final String NAME3 = "VAL3";
}
使用反射检索这些值,如下所示

Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
    String name = field.getName() ;
    String value = (String) field.get(name);
}

这是我第一次尝试反射。这是实现目标的正确方法吗?我想知道在这种情况下使用反射的陷阱是什么。

这不太正确-为了可读性,
get
的参数理想情况下应该是
null
:该参数的目的是在检索实例字段时给它一个目标

因此,您的代码可以是:

Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
    String name = field.getName() ;
    String value = (String) field.get(null);
}
现在,这应该可以了。。。但是你打算如何处理这些价值观呢?有什么理由要这样做,而不是创建一个直接公开的不可变的
Map

反射在需要的地方是可以的,但是您没有提供足够的信息来确定在这种情况下是否确实需要反射。

您的代码在静态字段和私有字段上都进行了迭代。因此,您应该检查是否只迭代静态字段

for (Field field : PARAMS.class.getFields()) {
    if (Modifiered.isStatic(field.getModifiers())) continue;
    String name = field.getName() ;
    String value = (String) field.get(PARAMS.class);
}
注意:正如Jon提到的,对于静态字段访问,实例参数被忽略。但是,我更喜欢传入类而不是null,因为这是一个更好的缩进文档

然而,更好的做法是使用注释对字段进行注释,这样您只得到那些您真正想要的字段,而不需要其他程序员(甚至是幕后的Java语言)添加其他静态字段。如果这样做,代码将如下所示

for (Field field : PARAMS.class.getFields()) {
    if (!field.isAnnotationsPresent(YourAnnotation.class)) continue;
    String name = field.getName() ;
    String value = (String) field.get(PARAMS.class);
}

另一个问题是,
getFields
返回此类及其所有超类的所有可访问字段(静态或非静态)。您发布的特定代码没有问题,因为唯一的超类是没有公共字段的
Object

我至少要测试字段是否在正确的类中声明-
getDeclaringClass()
,以及它是否具有正确的返回类型-
getType()

正如阿德里安所建议的,使用注释是最好的方法