Как сохранить программу, используя отражение / самоанализ? - PullRequest
0 голосов
/ 29 июля 2011

Когда я использую самоанализ, мои имена классов, методов и свойств пишутся в виде простого текста. Как в этой короткой демонстрации:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;



public class SO {
public static void main(String[] args)
        throws NoSuchMethodException, ClassNotFoundException,
        InvocationTargetException, IllegalAccessException, InstantiationException,    NoSuchFieldException {

    final Class<?> myClass = Class.forName("myClass");
    final Constructor<?> defaultConstructor = myClass.getDeclaredConstructor();
    final Object myInstance = defaultConstructor.newInstance();
    final Method myMethod = myClass.getDeclaredMethod("myMethod");
    myMethod.invoke(myInstance, "arg1", 3, true);
    final Field myFied = myClass.getDeclaredField("myFied");
    final Object value = myFied.get(myInstance);
}

}

Поскольку для этого кода нет проверки компиляции, он может прерваться во время выполнения, если какой-либо из моих целевых классов / методов / полей / сигнатур изменился в базе кода. Иногда IDE может помочь при рефакторинге, но часто мы можем пропустить изменение и получить фатальную ошибку во время выполнения.

Знаете ли вы какой-нибудь способ избежать такого рода проблем?

NB. Любой «Избегайте отражения, когда это возможно» без полезного ответа получит -1.
Это не угроза: мой вопрос не «должен ли я использовать самоанализ?» и я чувствую ответ чисто о том, что загрязняют вопрос.

Ответы [ 7 ]

4 голосов
/ 29 июля 2011

Знаете ли вы, как избежать подобных проблем?

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

Мне неизвестна какая-либо поддержка IDE для проверки отражающего кода на предмет возможных ошибок времени выполнения.На самом деле, в общем случае невозможно сделать, потому что это эквивалентно проблеме остановки.


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

3 голосов
/ 29 июля 2011

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

Поскольку ошибки такого типа будут появляться только во время выполнения, автоматическое тестирование является способом моделирования поведения во время выполнения в контролируемой среде.*

2 голосов
/ 29 июля 2011

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

Однако иногда вы не можете этого сделать (например, привязка bean-компонента Spring MVC, PropertyModels Wicket и т. Д.). В этих случаях, а также документирования (в методах get / set), что эти методы вызываются с отражением, я стремлюсь добавить статическую строку, например. для боба со свойством под названием фамилия

public static final String PROPERTY_SURNAME = "surname"

public String getSurname(...
public void setSurname(...

и используйте PROPERTY_SURNAME в коде, а не "surname". Это не поможет компилятору, но разработчик также намеревается изменить методы get / set.

2 голосов
/ 29 июля 2011

Я бы попытался провести рефакторинг любого кода, который использует жестко запрограммированное отражение для удаления жесткого кодирования.Например, вы можете изменить рефакторинг:

public Object getInstance() {

    return (Class.forName("myClass"));
}

как:

public Object getInstance(Class<?> clazz) {

    return (clazz.newInstance());
}

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

Еще лучше, вместо жесткого кодирования имени класса, метода или поля, вы можете аннотировать его, а затем использовать отражение для получения аннотированного элемента.

1 голос
/ 29 июля 2011

Вместо того, чтобы говорить «не использовать отражение», я скажу «попробуйте использовать Jython».

http://onjava.com/pub/a/onjava/2002/03/27/jython.html?page=2

Обратите внимание, что эта статья довольно старая на данный момент;Я предоставил это только в качестве примера.Например, «Python-кодеры редко используют простые методы get и set, предпочитая прямой доступ к переменной».part полностью игнорирует полезность встроенной в Python property() (которая была довольно новой в то время), которая позволяет использовать прозрачные методы получения и установки, обеспечивая лучшее из обоих миров.Но это отвлекается, так что, что угодно.

Да, модуль, на который вы, возможно, захотите взглянуть, - http://www.jython.org/docs/library/inspect.html

1 голос
/ 29 июля 2011

Ваш пример - маленький, чтобы давать много подсказок, но есть одна вещь, которую я иногда делаю:

Напишите интерфейс Java, содержащий методы, которые вы хотите вызвать.Используйте интерфейс, чтобы получить Объекты Метода для этого интерфейса.Затем используйте имя и параметры этого, чтобы найти метод, который вы действительно хотите вызвать.Например, один метод для интерфейса, поэтому имя класса указывает на операцию, которую вы хотите выполнить.

Ваш myClass не должен реализовывать интерфейс ...

1 голос
/ 29 июля 2011

Конечно.Избегайте отражения, когда это возможно.Поскольку целью размышлений является проверка типов, другого надежного способа проверки типов во время компиляции не существует.Если вы нашли способ для конкретного случая, вы можете избежать отражения в этом случае.

...