Недоліки рефлексії взагалі
Відображення важче зрозуміти, ніж прямолінійний код.
На мій досвід, рефлексія є функцією "експертного рівня" на Java. Я заперечую, що більшість програмістів ніколи не використовують рефлексію активно (тобто споживачі бібліотек, які використовують відображення, не враховуються). Це робить код, використовуючи його важче зрозуміти для цих програмістів.
Код відбиття недоступний для статичного аналізу
Припустимо, getFoo
у мене в класі є геттер, і я хочу його перейменувати getBar
. Якщо я не використовую жодного відображення, я можу просто шукати базу коду getFoo
і знайду кожне місце, де використовується getter, щоб я міг його оновити, і навіть якщо я пропущу його, компілятор поскаржиться.
Але якщо місце , яке використовує поглинач щось на зразок callGetter("Foo")
і callGetter
робить getClass().getMethod("get"+name).invoke(this)
, то описаний вище метод не знайде його, і компілятор буде скаржитися. Тільки коли код буде фактично виконаний, ви отримаєте NoSuchMethodException
. І уявіть, який біль ви відчуваєте, якщо цей виняток (який відслідковується) проковтнуто, callGetter
оскільки "він використовується лише з жорстко зашифрованими рядками, насправді це не може відбутися". (Ніхто не зробив би цього, хтось може сперечатися? За винятком того, що ОП зробив саме так у своїй відповіді "ТА". Якщо поле буде перейменовано, користувачі загального сетера ніколи не помітять, за винятком надзвичайно незрозумілої помилки сеттера, яка мовчки нічого не робить. Користувачі Getter, якщо їм пощастить, помітять консольний вихід ігнорованого винятку.)
Код відбиття не перевіряється типом компілятором
Це в основному великий підпункт вищезазначеного. Код відображення - це все Object
. Типи перевіряються під час виконання. Помилки виявляються одиничними тестами, але лише якщо у вас є покриття. ("Це просто геттер, мені не потрібно це перевіряти.") В основному ви втрачаєте перевагу, використовуючи Java над Python, ви здобули вас в першу чергу.
Код відображення недоступний для оптимізації
Можливо, не в теорії, але на практиці ви не знайдете JVM, який вбудовує або створює вбудований кеш Method.invoke
. Для таких оптимізацій доступні звичайні виклики методів. Це робить їх набагато швидшими.
Код відображення в цілому просто повільний
Пошук динамічного методу та перевірка типу, необхідні для коду відображення, повільніше, ніж звичайні виклики методу. Якщо ви перетворите цей дешевий однолінійний геттер у звіра-відбивача, ви, можливо, (я цього не вимірював) переглянули кілька порядків уповільнення.
Недоліком загального геттера / сеттера
Це просто погана ідея, адже зараз у вашому класі немає інкапсуляції. Кожне поле, яке воно має, є доступним. Ви також можете зробити їх загальнодоступними.