Подводные камни при получении значений переменных-членов в Java с отражением - PullRequest
0 голосов
/ 07 января 2010

У меня есть абстрактный класс следующим образом. Я хочу получить все значения переменных-членов.

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);
}

Я впервые экспериментирую с отражением. Это правильный способ достижения цели? Я хотел бы знать, каковы подводные камни в использовании отражения в этом случае.

Ответы [ 3 ]

4 голосов
/ 07 января 2010

Вы перебираете код по и статическим и закрытым полям. Поэтому вам следует проверить, что вы перебираете только статические поля.

for (Field field : PARAMS.class.getFields()) {
    if (Modifiered.isStatic(field.getModifiers())) continue;
    String name = field.getName() ;
    String value = (String) field.get(PARAMS.class);
}

NB: , как упоминал Джон, для доступа к статическому полю параметр экземпляра игнорируется. Однако я предпочитаю передавать класс вместо нуля, поскольку это лучшая документация по отступу.

Однако даже лучше практиковать аннотирование ваших полей, чтобы вы получали только те поля, которые вы действительно не хотите, чтобы другие статические поля добавлялись другими программистами (или даже языком Java за кулисами). Если вы сделаете это, ваш код будет выглядеть как

for (Field field : PARAMS.class.getFields()) {
    if (!field.isAnnotationsPresent(YourAnnotation.class)) continue;
    String name = field.getName() ;
    String value = (String) field.get(PARAMS.class);
}
3 голосов
/ 07 января 2010

Это не совсем правильно - аргумент для get в идеале должен быть null для удобства чтения: смысл этого аргумента в том, чтобы дать ему цель при извлечении instance поля.

Таким образом, ваш код может быть просто:

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

Теперь это должно сработать ... но что вы собираетесь делать с этими значениями? Есть ли какая-то причина, почему вы хотите сделать это, а не создавать неизменяемый Map<String, String>, который предоставляется напрямую?

Отражение в порядке, где это необходимо, но вы не предоставили достаточно информации, чтобы определить, действительно ли это необходимо в этом случае.

0 голосов
/ 07 января 2010

другая проблема, getFields возвращает все доступные поля (статические или нет) этого класса и все его суперклассы. Не проблема для определенного кода, который вы разместили, так как единственный суперкласс - Object, у которого нет открытого поля.
Я бы хотя бы проверил, объявлено ли поле в правильном классе - getDeclaringClass() - и имеет ли оно правильный тип возврата - getType()

Использование аннотации, как предположил Адриан, лучше всего ИМХО.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...