Недостатки размышлений в целом
Отражение сложнее понять, чем прямой код.
По моему опыту, отражение - это функция «экспертного уровня» в Java. Я бы сказал, что большинство программистов никогда не используют отражение активно (то есть использование библиотек, использующих отражение, не считается). Это затрудняет понимание кода для этих программистов.
Код отражения недоступен для статического анализа
Предположим, у меня getFoo
в классе есть получатель, и я хочу его переименовать getBar
. Если я не использую отражения, я могу просто найти базу кода getFoo
и найти все места, где используется геттер, чтобы я мог обновить его, и даже если я пропущу один из них, компилятор будет жаловаться.
Но если место, которое использует метод получения, является чем-то вроде callGetter("Foo")
и callGetter
делает getClass().getMethod("get"+name).invoke(this)
, то вышеупомянутый метод не найдет его, и компилятор не будет жаловаться. Только когда код действительно будет выполнен, вы получите NoSuchMethodException
. И представьте боль, в которой вы находитесь, если это исключение (которое отслеживается) проглатывается, callGetter
потому что «оно используется только с жестко закодированными строками, на самом деле это не может произойти». (Никто не станет этого делать, кто-то может поспорить? За исключением того, что ОП сделал именно это в своем ответе SO. Если поле переименовано, пользователи универсального установщика никогда не заметят, за исключением крайне неясной ошибки установщика, молча ничего не делающей. Пользователи получателя могут, если им повезет, заметить вывод консоли игнорируемого исключения.)
Код отражения не проверяется типом компилятором
Это в основном большой подпункт выше. Отражение кода это все о Object
. Типы проверяются во время выполнения. Ошибки обнаруживаются модульными тестами, но только если у вас есть покрытие. («Это всего лишь получатель, мне не нужно его проверять».) По сути, вы теряете преимущество, используя Java над Python, которое вы получили в первую очередь.
Код отражения недоступен для оптимизации
Возможно, не в теории, но на практике вы не найдете JVM, которая встроит или создаст встроенный кеш для Method.invoke
. Для такой оптимизации доступны обычные вызовы методов. Это делает их намного быстрее.
Отражение кода просто медленно
Динамический поиск методов и проверка типов, необходимые для кода отражения, выполняются медленнее, чем обычные вызовы методов. Если вы превратите этот дешевый однострочный геттер в зверя-отражателя, вы могли бы (я не измерял это) смотреть на несколько порядков замедления.
Недостаток универсального геттера / сеттера, в частности
Это просто плохая идея, потому что у вашего класса больше нет инкапсуляции. Каждое имеющееся поле доступно. Вы могли бы также сделать их всех публичными.