2016-10-04 2 views
0

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

for (Field f : this.getClass().getFields()) 
     { 
      try 
      { 
       Object o = f.get(this); 

       if (f.getType() == String.class) 
       { 
        //do things with the string 
       } 
      } 
      catch (Exception ex) 
      { 
       logger.error("Cannot get value for field. {}", ex.getMessage()); 
      } 

     } 

Это работает очень хорошо для такого громоздкого количества полей, как я полагаю, является точкой отражения. Меня попросили реорганизовать его, потому что он медленный (не так ли?).

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

+1

Я голосую, чтобы закрыть этот вопрос как не относящийся к теме, потому что у OP есть рабочий код и предлагается рефакторинг. Пожалуйста, посмотрите [ask] и попросите задать этот вопрос на [codereview.se]. – xenteros

+0

Лучше, положите весь класс. «Slow» - это зависит от использования класса и контента. Лично я считаю, что отражение здесь - лучшее решение ... если вы хотите сохранить ту же логику. Похоже, что это абстракция (беспорядок с 200 полями внутри одного класса необходимо обрабатывать и фильтровать много раз), а не серьезный недостаток реализации. – Les

+0

Это медленный? Кому ты рассказываешь. Поместите профайлер в свою программу и посмотрите, сколько времени он проводит в этом цикле. –

ответ

4

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

При условии, что вы используете сеттеры для изменения этих значений, вы можете реорганизовать класс для обновления Map<String,Object> всякий раз, когда вызывается сеттер. Это обеспечивает более быстрый доступ к полям, чем отражение, но может быть невозможно в зависимости от вашего варианта использования.

+0

Ах, очень приятно. К сожалению, поля являются общедоступными и устанавливаются напрямую. – Nanor

+1

@Nanor Одноразовые сеттеры будут полезны ...! – Kayaman

3

Большую часть времени тратится на получение объектов Field (и, возможно, их фильтрацию). Фактический поиск может быть довольно быстрым. Я использую ClassValue для кэширования этой информации и ее ускорения.

public enum StringFields { 
    INSTANCE; 

    final ClassValue<List<Field>> fieldsCache = new ClassValue<List<Field>>() { 
     @Override 
     protected List<Field> computeValue(Class<?> type) { 
      return Collections.unmodifiableList(
        Stream.of(type.getFields()) 
          .filter(f -> f.getType() == String.class) 
          .peek(f -> f.setAccessible(true)) // turn off security check 
          .collect(Collectors.toList())); 
     } 
    }; 

    public static List<Field> getAllStringFields(Class<?> type) { 
     return INSTANCE.fieldsCache.get(type); 
    } 
} 
+0

Итак, если бы я знал имя полей, я мог бы сделать Object.get (String) ', и это было бы быстрее? – Nanor

+0

@Nanor, если у вас есть кешированные объекты Field, это будет быстрее. Добавит пример, но занят atm –

1

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

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

Генерация кода может быть частью этапа построения.

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