sonyps4.ru

Введение в Java Reflection API. Повторяем поведение jQuery

  • JavaScript
  • Всем привет! Недавно услышал, как одни молодые фронтендеры пытались объяснить другим молодым фронтендерам, что такое Reflect в JavaScript. В итоге кто-то сказал, что это такая же штука, как прокси. Ситуация напомнила мне анекдот:

    Встречаются два майнера:
    - Ты что-нибудь понимаешь в этом?
    - Ну объяснить смогу.
    - Это понятно, но ты что-нибудь понимаешь в этом?

    Вот и с Reflect в JS для кого-то получилась такая же ситуация. Вроде бы что-то говорят, а для чего -  непонятно. В итоге я подумал, что стоит об этом рассказать еще раз простым языком с примерами.

    Сначала дадим определение, что такое рефлексия в программировании:
    Reflection/Reflect API  -  это API, который предоставляет возможность проводить реверс-инжиниринг классов, интерфейсов, функций, методов и модулей.

    Отсюда становится немного понятнее, для чего это API должно использоваться. Reflection API существует в разных языках программирования и, порой, используется для обхода ограничений, накладываемых ЯП. Также он используется для разработки различных вспомогательных утилит и для реализации различных паттернов (таких как Injection) и много чего еще.

    Например, Reflection API есть в Java. Он используется для просмотра информации о классах, интерфейсах, методах, полях, конструкторах и аннотациях во время выполнения java программ. К примеру, с помощью Reflection в Java можно использовать ООП паттерн  -  .

    В PHP тоже существует Reflection API, который позволяет не только делать реверс-инжиниринг, но даже позволяет получать doc-блоки комментариев, что используется в различных системах автодокументирования.

    В JavaScript Reflect  -  это встроенный объект, который предоставляет методы для перехватывания JavaScript операций. По сути, это неймспейс (как и Math). Reflect содержит в себе набор функций, которые называются точно так же, как и методы для Proxy.

    Некоторые из этих методов  -  те же, что и соответствующие им методы класса Object или Function. JavaScript растет и превращается в большой и сложный ЯП. В язык приходят различные вещи из других языков. На сегодня Reflect API умеет не так много, как в других ЯП. Тем не менее, есть предложения по расширению, которые еще не вошли в стандарт, но уже используются. Например, Reflection Metadata.

    Можно сказать, что неймспейс Reflect в JS  -  это результат рефакторинга кода. Мы уже пользовались ранее возможностями Reflect API, просто все эти возможности были вшиты в базовый класс   Object.

    Reflect Metadata / Metadata Reflection

    Это API создано для получения информации об объектах в рантайме. Это proposal, который пока не является стандартом. Сейчас активно используется полифил. На сегодняшний день активно применяется в Angular. С помощью этого API реализованы Inject и декораторы (анотаторы).

    Собственно ради Angular в TypeScript был добавлен расширенный синтаксис декораторов. Одной из интересных особенностей декораторов является возможность получать информацию о типе декорируемого свойства или параметра. Чтобы это заработало, нужно подключить библиотеку reflect-metadata, которая расширяет стандартный объект Reflect и включить опцию emitDecoratorMetadata к конфиге TS. После этого для свойств, которые имеют хотя бы один декоратор, можно вызвать Reflect.getMetadata с ключом «design:type».

    В чем различие Reflect от Proxy?

    Reflect  -  это набор полезных методов для работы с объектами, половина которых  -  это переписанные уже существующие из Object. Сделано это с целью улучшения семантики и наведения порядка, так как Object  -  это базовый класс, но при этом он содержит очень много методов, которые не должны в нем находиться. Также если вы создаете объект с пустым прототипом, то у вас исчезают методы рефлексии (ниже покажу на примере, что это значит).

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

    Use Cases

    Ну и рассмотрим способы применения Reflect API. Некоторые примеры уже давно известны, просто для этих целей мы привыкли использовать методы из класса Object. Но было бы правильнее, по логике, использовать их из пакета Reflect (пакеты  -  терминология из Java).

    Автогенерируемые поля объекта

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

    Const emptyObj = () => new Proxy({}, { get: (target, key, receiver) => (Reflect.has(target, key) || Reflect.set(target, key, emptyObj()), Reflect.get(target, key, receiver)) }) ; const path = emptyObj(); path.to.virtual.node.in.empty.object = 123; console.log(path.to.virtual.node.in.empty.object); // 123
    Все круто, но такой объект нельзя сериализовать в JSON, получим ошибку. Добавим магический метод сериализации  -  toJSON

    Console.clear(); const emptyObj = () => new Proxy({}, { get: (target, key, receiver) => (key == "toJSON" ? () => target: (Reflect.has(target, key) || Reflect.set(target, key, emptyObj()), Reflect.get(target, key, receiver))) }) ; const path = emptyObj(); path.to.virtual.node.in.empty.object = 123; console.log(JSON.stringify(path)); // {"to":{"virtual":{"node":{"in":{"empty":{"object":123}}}}}}

    Динамический вызов конструктора

    Имеем:

    Var obj = new F(...args)
    Но хотим уметь динамически вызывать конструктор и создавать объект. Для этого есть Reflect.construct:

    Var obj = Reflect.construct(F, args)
    Может понадобиться для использования в фабриках (ООП гайз поймут). Пример:

    // Old method function Greeting(name) { this.name = name } Greeting.prototype.greet = function() { return `Hello ${this.name}` } function greetingFactory(name) { var instance = Object.create(Greeting.prototype); Greeting.call(instance, name); return instance; } var obj = greetingFactory("Tuturu"); obj.greet();
    Как такое пишется в 2017 году:

    Class Greeting { constructor(name) { this.name = name } greet() { return `Hello ${this.name}` } } const greetingFactory = name => Reflect.construct(Greeting, ); const obj = greetingFactory("Tuturu"); obj.greet();

    Повторяем поведение jQuery

    Следующая строка показывает как можно сделать jQuery в 2 строки:

    Const $ = document.querySelector.bind(document); Element.prototype.on = Element.prototype.addEventListener;
    Удобно, если нужно что-то быстро наваять без зависимостей, а писать длинные нативные конструкции лень. Но в этой реализации есть минус - выбрасывает исключение при работе с null:

    Console.log($("some").innerHTML); error TypeError: Cannot read property "innerHTML" of null
    Используя Proxy и Reflect можем переписать этот пример:

    Const $ = selector => new Proxy(document.querySelector(selector)||Element, { get: (target, key) => Reflect.get(target, key) }) ;
    Теперь при попытке обращения к null свойствам просто будем получать undefined:

    Console.log($("some").innerHTML); // undefined

    Так почему же надо использовать Reflect?

    Reflect API более удобен при обработке ошибок. К примеру, всем знакома инструкция:
    Object.defineProperty(obj, name, desc)

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

    Try { Object.defineProperty(obj, name, desc); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) } /* --- OR --- */ if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
    Это позволяет обрабатывать ошибки через условия, а не try-catch. Пример применения Reflect API с обработкой ошибки:

    Try { var foo = Object.freeze({bar: 1}); delete foo.bar; } catch (e) {}
    А теперь можно писать так:

    Var foo = Object.freeze({bar: 1}); if (Reflect.deleteProperty(foo, "bar")) { console.log("ok"); } else { console.log("error"); }
    Но надо сказать, что есть случаи, когда Reflect также выбрасывает исключения.

    Некоторые записи выходят короче

    Без лишних слов:

    Function.prototype.apply.call(func, obj, args) /* --- OR --- */ Reflect.apply.call(func, obj, args)

    Разница в поведении

    Пример без слов:

    Object.getPrototypeOf(1); // undefined Reflect.getPrototypeOf(1); // TypeError
    Вроде бы все понятно. Делаем выводы, что лучше. Reflect API более логичный.

    Работа с объектами с пустым прототипом

    Дано:

    Const myObject = Object.create(null); myObject.foo = 123; myObject.hasOwnProperty === undefined; // true // Поэтому приходится писать так: Object.prototype.hasOwnProperty.call(myObject, "foo"); // true
    Как видите, мы уже не имеем методов рефлексии, например, hasOwnProperty. Поэтомы мы либо пользуемся старым способом, обращаясь к прототипу базового класса, либо обращаемся к Reflect API:

    Reflect.ownKeys(myObject).includes("foo") // true

    Выводы

    Reflect API - это результат рефакторинга. В этом неймспейсе содержатся функции рефлексии, которые раньше были зашиты в базовые классы Object, Function… Изменено поведение и обработка ошибок. В будущем этот неймспейс будет расширяться другими рефлективными инструментами. Так же Reflect API можно считать неотъемлемой частью при работе с Proxy (как видно из примеров выше).

    Macrium Reflect Free - простая бесплатная утилита для бэкапа и создания Image-копий жесткого диска. Бесплатно скачать Macrium Reflect Free Edition последней версии для Windows 30-дневную пробную версию. Постоянная ссылка: сайт/ru/backups/macriumreflect

    Эта утилита служит для создания и использования резервных данных жесткого диска на операционной системе Microsoft Windows. Для работы нужно скачать Macrium Reflect Free Edition RUS бесплатно для Windows 10, 8..

    Краткое описание Macrium Reflect Free

    Процедуру копирования в резерв называют по-разному: и бикап, и букап, и бэкап и даже быкап, но процесс является примитивным резервированием данных. С задачей резервного копирования может справиться множество программ, как распространяемых за деньги, так и бесплатных, и Макриум Рефлект Фрее - одна из таких.

    Юзабилити, интерфейс, функциональные возможности

    Использование очень удобно, не требует особого внимания от пользователя, может быть, поэтому не случайна высокая оценка программы по юзабильности. Не русский интерфейс Macrium Reflect Free интуитивно понятен, но если возникли вопросы по работе с утилитой, можно скачать видео уроки с торрентов (torrent) или посетить официальный сайт.

    Функции программы резервного копирования MRF:

    Программа создает копию диска, используя сервис теневых копий Microsoft.
    - Хранить резервные копии дисков можно на DVD-накопителях, USB, а также на сетевых устройствах и FireWire.
    - Макриум Рефлект Фри Эдишн оснащен встроенным менеджером планирования для создания в автоматическом режиме копий.
    - Высокая скорость и серьезные степени сжатия копируемого диска.
    - Установлены плагины для восстановления диска при помощи BartPE Rescue.
    - Настройка системного журнала в HTML-формате.
    - Так же можно создать восстановительный диск, где можно использовать графический интерфейс и настроить сетевые доступы.

    Данный надежный программный продукт для резервирования жестких дисков, несомненно, достоин того, чтобы в последней версии ПО Macrium Reflect Free скачать бесплатно без регистрирования и SMS. На официальном сайте компании можно получить помощь от тех. поддержки компании, оставить комментарии, отзывы, скачать инструкцию с описанием работы программы, поставить оценку использования этого продукта, также можно купить платную версию. Настоятельно рекомендуем или включить автообновление, или скачать Macrium Reflect Free 30-дневную пробную версию с этой страницы programmywindows.com на русском языке в последней версии для компьютера совершенно бесплатно. Облегчить себе поиск обновлений не сложно, просто качайте обновления здесь.

    Macrium Reflect инструкция пользователя

    Вступление.

    Macrium Reflect - бесплатная программа для создания образов жестких дисков и разделов. Программа позволяет как создавать, так и восстанавливать разделы, так же доступна опция просмотра созданных бекапов, и их редактирование. Благодаря точному алгоритму создания образов, Macrium Reflect в считанные минуты создает бекап практически любого раздела, сжимая данные в несколько раз. Так диск C:/ размером в 30 гигабайт, с занятым пространством в 11 гигабайт был сжат в образ размером в 3,88 гигабайта.

    Применение.

    Одна из главных причин использования программы Macrium Reflect - экономия времени. Для наглядности приведу простой пример. После установки операционной системы Windows пользователь начинает постепенно наполнять ее софтом, со временем, подборка программного обеспечения на компьютере сводится к использованию одних и тех же программ. Для офисной работы используется LibreOffice, для прослушивания музыки Winyl, либо WinAmp, тот же Aimp достоин внимания, для просмотра видео - VLC. Для выполнения узкоспециализированных задач - иной софт.

    Так вот, а теперь представим себе что в один прекрасный момент просто необходимо переустановить систему, причин по которой она будет работать с перебоями предостаточно - будь-то действие вирусов, аппаратный сбой, или просто - «пришло время». Сама переустановка Windows не несет в себе ничего хлопотного, основная часть работы состоит в установке необходимого программного обеспечения, а на это может уйти ни один день. Каков выход из сложившейся ситуации? Правильно, использование программ способных создать копию раздела жесткого диска. Именно программа Macrium Reflect и способна удовлетворить нашу потребность, к тому же она бесплатна.

    Пошаговая инструкция.

    И так, прежде всего, для того что бы работа с программой принесла удовольствие, стоит изначально потрудиться. Для этого стоит выделить время, и переустановить систему с нуля. То есть, отформатировать раздел на котором планируется разместить операционную систему, установить ее, после чего инсталлировать все драйвера, и тот набор программ который жизненно необходим в повседневной работе. Если на текущий момент ОС"ь работает как часики, предыдущий совет можно опустить, решайте сами.

    И так, ОС установлена, драйвера на месте, программы там же:). Устанавливаем Macrium Reflect, сама инсталляция программы не отличается от стандартной процедуры установки программ, надеюсь трудностей она не вызовет.

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



    Для начала создания образа вызываем «Мастер создания образов»:

    Так выглядит приветствие «Мастера создания образов»



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



    Следующий шаг потребует от нас указания в места для хранения самого образа раздела:



    Доступны для работы следующие пункты:

    • Локальный диск - раздел жесткого диска (отличный от того, образ которого мы создаем), это может быть диск D:
    • Сетевой ресурс - если есть доступ к сетевым дискам, папкам, образ можно сохранить там.
    • CD/DVD диск - при наличии пишущего привода, образ можно записать непосредственно на сам диск.

    Кстати, рекомендую сохранить образ, изначально, на другом разделе локального диска, такой вариант подразумевает меньший процент ошибок во время создания образа. Потом его можно скопировать на сколь угодное количество флешек, cd-r"ок и прочих носителей, для предотвращения потери образа.

    В нижней части текущего окна можно задать имя будущего образа, если этого не сделать Macrium Reflect автоматически пропишет имя образа. Кстати. Этот вариант рекомендуют сами разработчики.

    Финальное окно мастера позволяет нам указать степень сжатия будущего образа (кнопка Adnavced), но, установки по умолчанию работают прекрасно, и что-то изменять просто нет смысла.



    Жмем Finish, в появившемся окошке ОК, и идем пить кофе, на создание образа может уйти от 5 до 10 минут, все зависит от размера раздела образ которого мы создаем.



    По окончанию резервного копирования программа выведет итоговую информацию:



    Все готово, образ успешно создан.

    Теперь, если система стала «барахлить», и ее просто необходимо переустановить, нет надобности проводить за компьютером пол дня, стоит только восстановить созданный нами образ обратно на диск C:/ и продолжить работу.

    Восстановление.

    Создаем загрузочный диск.

    Для начала создания загрузочного диска запускаем мастер:


    Главное окно мастера предлагает нам два варианта для создания загрузочного диска, на основе ОС Linux, либо Bart PE.



    Причем, создание образа на базе BartPe недоступна из под Windows Vista/7. Создание загрузочного диска может происходить непосредственно на cd-r, либо в iso-файл. Второй вариант предпочтительней, так как в дальнейшем образ можно скопировать на флешку, и загрузиться с нее. Сделать это можно программой .

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

    Основной смысл это: выбрать наш файл-образ -> указать какой раздел мы будет восстанавливать -> указать на какой раздел мы его распаковываем -> и вперед:) ...





















    Если что-то непонятно прошу всех в комментарии к статье, но, лучше в ветку форума -

    Просмотров: 54963

    Рефлексия (от позднелат. reflexio - обращение назад) - это механизм исследования данных о программе во время её выполнения. Рефлексия позволяет исследовать информацию о полях, методах и конструкторах классов. Можно также выполнять операции над полями и методами которые исследуются. Рефлексия в Java осуществляется с помощью Java Reflection API. Этот интерфейс API состоит из классов пакетов java.lang и java.lang.reflect. С помощью интерфейса Java Reflection API можно делать следующее:

    • Определить класс объекта.
    • Получить информацию о модификаторах класса, полях, методах, конструкторах и суперклассах.
    • Выяснить, какие константы и методы принадлежат интерфейсу.
    • Создать экземпляр класса, имя которого неизвестно до момента выполнения программы.
    • Получить и установить значение свойства объекта.
    • Вызвать метод объекта.
    • Создать новый массив, размер и тип компонентов которого неизвестны до момента выполнения программ.

    Получение объекта типа Class

    MyClass a = new MyClass(); Class aclass = a.getClass(); Самое простое, что обычно делается в динамическом программировании, - это получают объект типа java.lang.Class. Если у нас есть экземпляр объекта Class мы можем получить всевозможную информацию об этом классе и даже осуществлять операции над ним. Вышеприведенный метод getClass() часто полезен тогда когда есть экземпляр объекта, но не известно какого класса этот экземпляр. Если у нас есть класс, для которого в момент компиляции известен тип, то получить экземпляр класса ещё проще. Class aclass = MyClass.class; Class iclass = Integer.class; Если имя класса не известно в момент компиляции, но становится известным во время выполнения программы, можно использовать метод forName(), чтобы получить объект Class. Class c = Class.forName("com.mysql.jdbc.Driver");

    Получение имени класса

    Class c = myObject.getClass(); String s = c.getName(); Объект типа String, возвращаемый методом getName(), будет содержать полностью уточненное имя класса, т.е. если типом объекта myObject будет Integer, то результат будет вида java.lang.Integer .

    Исследование модификаторов класса

    Class c = obj.getClass(); int mods = c.getModifiers(); if (Modifier.isPublic(mods)) { System.out.println("public"); } if (Modifier.isAbstract(mods)) { System.out.println("abstract"); } if (Modifier.isFinal(mods)) { System.out.println("final"); } Чтобы узнать, какие модификаторы были применены к заданному классу, сначала нужно с помощью метода getClass получить объект типа Class, представляющий данный класс. Затем нужно вызвать метод getModifiers() для объекта типа Class, чтобы определить значение типа int, биты которого представляют модификаторы класса. После этого можно использовать статические методы класса java.lang.reflect.Modifier, чтобы определить, какие именно модификаторы были применены к классу.

    Нахождение суперклассов

    Class c = myObj.getClass(); Class superclass = c.getSuperclass(); Можно также использовать метод getSuperclass() для объекта Class, чтобы получить объект типа Class, представляющий суперкласс рефлексированного класса. Нужно не забывать учитывать, что в Java отсутствует множественное наследование и класс java.lang.Object является базовым классом для всех классов, вследствие чего если у класса нет родителя то метод getSuperclass вернет null. Для того чтобы получить все родительские суперклассы, нужно рекурсивно вызывать метод getSuperclass().

    Определение интерфейсов, реализуемых классом

    Class c = LinkedList.class; Class interfaces = c.getInterfaces(); for(Class cInterface: interfaces) { System.out.println(cInterface.getName()); } С помощью рефлексии можно также определить, какие интерфейсы реализованы в заданном классе. Метод getInterfaces() вернет массив объектов типа Class. Каждый объект в массиве представляет один интерфейс, реализованный в заданном классе.

    Исследование, получение и установка значений полей класса.

    Class c = obj.getClass(); Field publicFields = c.getFields(); for (Field field: publicFields) { Class fieldType = field.getType(); System.out.println("Имя: " + field.getName()); System.out.println("Тип: " + fieldType.getName()); } Чтобы исследовать поля принадлежащие классу, можно воспользоваться методом getFields() для объекта типа Class. Метод getFields() возвращает массив объектов типа java.lang.reflect.Field, соответствующих всем открытым полям объекта. Эти открытые поля необязательно должны содержаться непосредственно внутри класса, с которым вы работаете, они также могут содержатся в суперклассе, интерфейсе или интерфейсе представляющем собой расширение интерфейса, реализованного классом. С помощью класса Field можно получить имя поля, тип и модификаторы. Если известно имя поля, то можно получить о нем информацию с помощью метода getField() Class c = obj.getClass(); Field nameField = c.getField("name"); Методы getField() и getFields() возвращают только открытые члены данных класса. Если требуется получить все поля некоторого класса нужно использовать методы getDeclaredField() и getDeclaredFields(). Эти методы работают точно также как их аналоги getField() и getFields(), за исключением того, что они возвращают все поля, включая закрытые и защищенные. Чтобы получить значение поля, нужно сначала получить для этого поля объект типа Field затем использовать метод get(). Метод принимает входным параметром ссылку на объект класса. Class c = obj.getClass(); Field field = c.getField("name"); String nameValue = (String) field.get(obj) Так же у класса Field имеются специализированные методы для получения значений примитивных типов: getInt(), getFloat(), getByte() и др.. Для установки значения поля, используется метод set(). Class c = obj.getClass(); Field field = c.getField("name"); field.set(obj, "New name"); Для примитивных типов имеются методы setInt(), setFloat(), setByte() и др. Вопрос к читателю, можно ли изменить значение private поля? А private final? Ответ узнаем чуть позже.

    Исследование конструкторов класса

    Class c = obj.getClass(); Constructor constructors = c.getConstructors(); for (Constructor constructor: constructors) { Class paramTypes = constructor.getParameterTypes(); for (Class paramType: paramTypes) { System.out.print(paramType.getName() + " "); } System.out.println(); } Чтобы получить информацию об открытых конструкторах класса, нужно вызвать метод getConstructors() для объекта Class. Этот метод возвращает массив объектов типа java.lang.reflect.Constructor. С помощью объекта Constructor можно затем получить имя конструктора, модификаторы, типы параметров и генерируемые исключения. Можно также получить по отдельному открытому конструктору, если известны типы его параметров. Class paramTypes = new Class { String.class, int.class }; Constructor aConstrct = c.getConstructor(paramTypes); Методы getConstructor() и getConstructors() возвращают только открытые конструкторы. Если требуется получить все конструкторы класса, включая закрытые можно использовать методы getDeclaredConstructor() и getDeclaredConstructors() эти методы работают точно также, как их аналоги getConstructor() и getConstructors().

    Исследование информации о методе, вызов метода.

    Class c = obj.getClass(); Method methods = c.getMethods(); for (Method method: methods) { System.out.println("Имя: " + method.getName()); System.out.println("Возвращаемый тип: " + method.getReturnType().getName()); Class paramTypes = method.getParameterTypes(); System.out.print("Типы параметров: "); for (Class paramType: paramTypes) { System.out.print(" " + paramType.getName()); } System.out.println(); } Чтобы получить информацию об открытых методах класса, нужно вызвать метод getMethods() для объекта Class. Этот метод возвращает массив объектов типа java.lang.reflect.Method. Затем с помощью объекта Method можно получить имя метода, тип возвращаемого им значения, типы параметров, модификаторы и генерируемые исключения. Также можно получить информацию по отдельному методу если известны имя метода и типы параметров. Class c = obj.getClass(); Class paramTypes = new Class { int.class, String.class}; Method m = c.getMethod("methodA", paramTypes); Методы getMethod() и getMethods() возвращают только открытые методы, для того чтобы получить все методы класса не зависимо от типа доступа, нужно воспользоватся методами getDeclaredMethod() и getDeclaredMethods(), которые работают точно также как и их аналоги (getMethod() и getMethods()). Интерфейс Java Reflection Api позволяет динамически вызвать метод, даже если во время компиляции имя этого метода неизвестно (Имена методов класса можно получить методом getMethods() или getDeclaredMethods()). В следующем примере рассмотрим вызов метода зная его имя. Например метод getCalculateRating: Class c = obj.getClass(); Class paramTypes = new Class { String.class, int.class }; Method method = c.getMethod("getCalculateRating", paramTypes); Object args = new Object { new String("First Calculate"), new Integer(10) }; Double d = (Double) method.invoke(obj, args); В данном примере сначала получаем объект Method по имени метода getCalculateRating, затем вызываем метод invoke() объекта Method, и получаем результат работы метода. Метод invoke принимает два параметра, первый - это объект, класс которого объявляет или наследует данный метод, а второй - массив значений параметров, которые передаются вызываемому методу. Если метод имеет модификатор доступа private, тогда выше приведённый код нужно модифицировать таким образом, для объекта Method вместо метода getMethod() вызываем getDeclaredMethod(), затем для получения доступа вызываем setAccessible(true) .

    Method method = c.getDeclaredMethod("getCalculateRating", paramTypes); method.setAccessible(true);

    Загрузка и динамическое создание экземпляра класса

    Class c = Class.forName("Test"); Object obj = c.newInstance(); Test test = (Test) obj; С помощью методов Class.forName() и newInstance() объекта Class можно динамически загружать и создавать экземпляры класса в случае, когда имя класса неизвестно до момента выполнения программы. В приведенном коде мы загружаем класс с помощью метода Class.forName(), передавая имя этого класса. В результате возвращается объект типа Class. Затем мы вызываем метод newInstance() для объекта типа Class, чтобы создать экземпляры объекта исходного класса. Метод newInstance() возвращает объет обобщенного типа Object, поэтому в последней строке мы приводим возвращенный объект к тому типу, который нам нужен.

    И напоследок, пример модификации private полей.

    import java.lang.reflect.Field; class WithPrivateFinalField { private int i = 1; private final String s = "String S"; private String s2 = "String S2"; public String toString() { return "i = " + i + ", " + s + ", " + s2; } } public class ModifyngPrivateFields { public static void main(String args) throws Exception { WithPrivateFinalField pf = new WithPrivateFinalField(); Field f = pf.getClass().getDeclaredField("i"); f.setAccessible(true); f.setInt(pf, 47); System.out.println(pf); f = pf.getClass().getDeclaredField("s"); f.setAccessible(true); f.set(pf, "MODIFY S"); System.out.println(pf); f = pf.getClass().getDeclaredField("s2"); f.setAccessible(true); f.set(pf, "MODIFY S2"); System.out.println(pf); } } Из приведённого кода видно что private поля можно изменять. Для этого требуется получить объект типа java.lang.reflect.Field с помощью метода getDeclaredField(), вызвать метод setAccessible(true) и с помощью метода set() устанавливаем значение поля. Учтите что поле final при выполнении данной процедуры не выдаёт предупреждений, а значение поля остаётся прежним, т.е. final поля остаются неизменные.




    Загрузка...