Reflection (Рефлексія) - основи
На мій погляд, рефлексія для Java нагадує електрику в життя звичайної людини - все їм дуже активно користуються, але як воно реально працює, мало хто знає досконально і це незнання зовсім не заважає. Є загальне розуміння - і досить.
Рефлексія як ідея і інструмент вкрай важлива для розуміння величезної кількості технологій, пакетів та іншого. Тому розуміти, що це таке і знати основи вкрай важливо.
З іншого боку, використання безпосередньо Reflection API (набір функцій для рефлексії) в життя звичайного програміста, який займається прикладними системами, зустрічається досить рідко.
Тобто знати, що це таке, розуміти основи і тримати в голові плюси і мінуси - це просто необхідно. Чи необхідно досконально пам'ятати набір функцій. Навряд чи ви часто будете їх використовувати. На мій погляд, краще розуміти рефлексію і знати куди йти за додатковою інформацією. Хоча звичайно ж багато що залежить від вашого конкретного проекту - може саме ваш буде просто "завалений" кодом з використанням Reflection API. і ви досягнете такого розуміння цього питання, який рідко зустрічається серед професіоналів. Хто знає.
Так що ж таке рефлексія і які завдання вона дозволяє вирішувати?
Якщо брати технічні можливості, то в першу чергу можна виділити дві групи дій:
- Можна дізнатися всю інформацію про клас - методи, поля, конструктори, константи, суперклас, реалізовані класом інтерфейси.
- Можна працювати з класом (об'єктом), а саме - створити об'єкт класу, виконати методи, отримати або встановити значення полів.
Якщо розширити список, то ось що дозволяє виконати рефлексія:
- Дізнатися / визначити клас об'єкта
- Отримати інформацію про модифікатори класу, полях, методах, константи, конструкторах і суперклас.
- З'ясувати, які методи належать реалізується інтерфейсу / інтерфейсів.
- Створити екземпляр класу, причому ім'я класу невідомо до моменту виконання програми.
- Отримати і встановити значення поля об'єкту по імені.
- Викликати метод об'єкта по імені.
І ще раз в короткій формі - рефлексія дозволяє вам отримати інформацію про внутрішню будову класу - поля, методи і т.д. - і дозволяє звернутися до полів, методів і іншим артіфактов через цю інформацію.
Причому, що найважливіше - ЦЕ ВСЕ МОЖНА РОБИТИ ВЖЕ ПРИ ВИКОНАННІ ПРОГРАМИ - як часто кажуть, в Рантайм (runtime).
Якщо ви ніколи не стикалися з такого роду механізмами, то у вас може виникнути цілком резонне питання - а навіщо все це треба. Відповідь в цьому випадку досить простий, але в той же час дуже невизначений - ви кардинально підвищуєте гнучкість і можливість налаштовувати вашу програму.
Використовуючи рефлексію програма може викликати абсолютно невідомий метод абсолютно невідомого класу вже під час свого виконання. У момент компіляції про це класі і методі було абсолютно нічого не відомо. Рефлексія використовується практично у всіх сучасних технологіях Java. Складно собі уявити, могла б Java як платформа досягти такого великого поширення без рефлексії. Швидше за все не змогла б.
Перше знайомство
Розглянемо нескладний варіант використання рефлексії. Ваша програма за розкладом (або якось інакше) має виконати певний метод певного класу. Наприклад, вам необхідно завантажувати оновлення фінансової інформації.
До якогось часу ця інформація знаходилася в базі даних і метод класу вмів цю інформацію з цієї бази отримувати.
Якщо проектування велося з урахуванням можливої заміни класу, то швидше за все був визначений інтерфейс і була зроблена реалізація у вигляді класу для бази даних. Щось на зразок такого варіанту.
Сама структура, яку отримуємо з інтерфейсу може бути якимось класом
FinanceInfoBuilder builder = (FinanceInfoBuilder) cl. newInstance ();
Метод newInstance () дозволяє створити об'єкт зазначеного класу. Але що ВАЖЛИВО відзначити - такий виклик можливий тільки в разі, якщо клас має конструктор БЕЗ параметрів. Якщо такого конструктора в вашому класі немає, то скористатися таким простим викликом не вийде - доведеться діяти складніше. Так що мати конструктор без параметрів - це непогана ідея.
Як ви вже можливо здогадалися, виклик повертає об'єкт класу Object і нам треба вручну привести його до потрібного типу. Оскільки ми покладаємося на "порядність" нашого класу, яка виражається в підтримці інтерфейсу FinanceInfoBuilder, то ми до нього і наводимо наш об'єкт.
Тепер для зміни класу для завантаження фінансових показників досить просто відредагувати файл builder.properties. Нічого більше. Далі йдуть бурхливі тривалі оплески.
Проект в NetBeans можна завантажити тут: FinanceExample
клас Class
Ми подивилися варіант завантаження класу і створення об'єкта потрібного нам класу. Насправді такий варіант використання рефлексії вельми поширений. Так що дуже рекомендую запам'ятати це рішення. Тепер ми подивимося, як можна не тільки створити об'єкт потрібного класу, але і як можна звернутися до полів або методів.
Визначимо простий клас для наших експериментів
Проект в NetBeans можна завантажити тут: SimpleReflection