Использование отражения вместо длинного оператора switch - PullRequest
0 голосов
/ 20 февраля 2020

Эй, у меня есть довольно длинный оператор switch, который вызывает метод, основанный на такой строке:

private void callMethod(String name) {
    switch(name) {
        case "blah":
            blah();
            break;
        case "method":
            method()
            break;
    }
}

et c.

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

try {
    Method method = ClassName.class.getDeclaredMethod(name, args);
    method.invoke(args);
} catch (NoSuchMethodException e) {
    // switch default
}

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

Редактировать: причина, по которой я ее использовал, заключается в том, что у пользователя есть возможность запустить другую часть игры в зависимости от введенной строки. Каждый метод, запускающий событие названо в честь того, что им нужно ввести.

Ответы [ 2 ]

2 голосов
/ 20 февраля 2020

Отражение - обычно худший способ сделать что-то. Это медленно, оно не может быть оптимизировано во время выполнения, и компилятор не может отмечать ошибки. И, как указала kp ie, предоставление пользователю возможности напрямую контролировать, какой метод выполняется, является дырой в безопасности.

Любой длинный оператор switch можно заменить на Map. В вашем случае достаточно Map<String, Runnable>:

Map<String, Runnable> actions = new HashMap<>();
actions.put("blah", this::blah);
actions.put("method", this::method);

// ...

Runnable action = actions.get(name);
if (action == null) {
    throw new IllegalArgumentException("Invalid name: " + name);
}
action.run();
2 голосов
/ 20 февраля 2020

Использование такого отражения - плохая идея. Посмотрите здесь для получения информации о недостатках.

О производительности:

"Поскольку отражение включает типы, которые динамически разрешаются, определенная Java виртуальная машина оптимизация не может быть выполнена. Следовательно, отражающие операции имеют более низкую производительность, чем их неотражающие аналоги, и их следует избегать в разделах кода, которые часто вызываются в чувствительных к производительности приложениях. "

Не ' не думайте о рефлексии как о нормальном инструменте, подобном String или ArrayList, и скорее пытайтесь реализовать лучший дизайн программного обеспечения, соответствующий вашим потребностям. Тогда вам придется очень редко задумываться о рефлексии.


Редактировать:

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

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

...