Эффективное использование Отражения Java - действительно ли это - взлом или является этой общепринятой практикой?

Эй, долговременный слушатель в первый раз вызывающая сторона, и я задаю вопрос, связанный с отражением Java, и как легкий это предоставляет себя по-видимому ужасному кодированию. Следующий метод пытается взять два подобных объекта (один объект, имеющий все поля другого объекта и затем некоторых) и сравнить двух из них для равенства. Это (предположительно) возвратит true, если методы считывания, которые совместно используют объекты, будут равны, и возвратят false, если они не равны.

public boolean validateArchive( Object record, Object arcRecord ) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
    log.debug( record.getClass().toString() );

    Object methodValue;
    Object arcMethodValue;

    for ( Method method : record.getClass().getMethods() )
    {
        if ( method.getTypeParameters().length == 0 && method.getName().startsWith( "get" ) && !method.getName().startsWith( "getClass" ) )
        {
            methodValue = method.invoke( record );
            arcMethodValue = arcRecord.getClass().getMethod( method.getName() ).invoke( arcRecord );

            log.debug( "Method name: " + method.getName() );
            log.debug( "Archive value: " + arcMethodValue );
            log.debug( "Object value: " + methodValue );

            if ( arcMethodValue != null && methodValue != null && !arcMethodValue.equals( methodValue ) )
            {
                return false;
            }
            else
            {
                if ( arcMethodValue == null && methodValue != null || methodValue == null && arcMethodValue != null )
                {
                    return false;
                }
            }
        }
    }

    return true;
}

Этот метод делает то, что я ожидаю, что это сделает в модульных тестах, но это выглядит ужасным, и чувствует себя неправильным (я - особенно не поклонник вложенного 'если'). Я просто надеялся на некоторые указатели о том, как сделать это более эффективно/эффективно. Если я нарушил некоторое правило регистрации, не стесняйтесь исправлять меня, я стремлюсь учиться и т.д.

5
задан Gilles 'SO- stop being evil' 19 July 2013 в 10:44
поделиться

4 ответа

Для этой конкретной задачи я бы рекомендовал реализовать метод equals в классах, которые будут сравниваться, если у вас нет этой опции (например, если у вас нет исходного кода для исходного класса). IDE, такие как IntelliJ, предоставляют поддержку для создания методов «равно» и «хэш-код» (в IntelliJ вы указываете поля, которые будут сравниваться, и какие поля могут быть нулевыми или нет). В этом конкретном случае я бы посоветовал использовать эти инструменты.

Есть один случай, когда я думаю, что реализация с использованием Reflection была бы полезной - в модульном тесте, если вы хотите выдать ошибку утверждения, если равенство не истинно, вы можете фактически выдать утверждение для точного поля, которое не работает, и это не просто общая ошибка утверждения типа «объект не такой же» - даже в этом случае я бы выполнил равенство после моей первоначальной проверки, чтобы убедиться, что объекты совпадают, или по крайней мере, что метод equals реализован и работает правильно.

PS: Если вы хотите избавиться от всего этого кода, проверьте библиотеку Beans Common ; PS 2: Отражение неплохое, и оно используется везде, где вы этого не сделаете. иметь явный кодовый вызов - например, файлы конфигурации Spring. Только не злоупотребляйте этим.

6
ответ дан 14 December 2019 в 01:06
поделиться

visokio.com имеет загружаемые коллекции векторных карт здесь: http://www.visokio.com/maps большинство из них поддерживают десятичные координаты широты/долготы.

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

hth.

edit : попадайтесь на них при просмотре википедии:

-121--2583743-

Кажется, что отсутствует одна основная точка: обход каталога включает чтение данных с диска Даже когда/если эти данные находятся в кэше, вы в конечном итоге проходите через достаточное количество кода, чтобы получить его из кэша в свой процесс. Пути также, как правило, довольно короткие - любое больше, чем пара сотен байт довольно необычно. Вместе это означает, что вы можете довольно разумно построить последовательности для всех путей, которые вам нужны без каких-либо реальных проблем. Время, затраченное на построение последовательностей, все еще довольно мало по сравнению со временем чтения данных с диска. Это означает, что обычно можно игнорировать время, затраченное на управление последовательностями, и работать исключительно над оптимизацией использования диска.

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

-121--2579239-

Поскольку вы ищете только «свойства», вы могли бы использовать commons beantils и точнее этого класса ...

(Я думаю, что вы не можете реализовать .equals, потому что ваши объекты не имеют общего типа...)

2
ответ дан 14 December 2019 в 01:06
поделиться

Я считаю, что вы проверяете ненужные случаи в ваших if утверждениях, и можете сократить их до этого:

if ( arcMethodValue == null ) {
    if ( methodValue != null) {
        return false;
    }
} else if ( !arcMethodValue.equals( methodValue ) ) {
    return false;
}

Также, вы вызываете method.getName() 4 раза, вы могли бы создать переменную и затем использовать ее.

1
ответ дан 14 December 2019 в 01:06
поделиться

Ваш код возврата излишне сложен. Стандартная идиома для сравнения ссылочных типов следующая:

  (field1 == null) ? (field2 == null) : field1.equals(field2);

Это гораздо яснее и довольно стандартно (Эффективное издание Java 2, стр. 43).


Обновление:

Произошла путаница, поскольку ранее я написал return [idiom] . Да, в этом случае возврат не будет тем, чего хочет исходный плакат. Он хотел бы , если! [Идиома] вернет ложь; вместо этого. Я хочу сказать, что [идиома] работает, и это намного лучше.

0
ответ дан 14 December 2019 в 01:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: