Чтобы понять принцип размышления, вы должны сначала понять, какой тип информации. Java позволяет нам идентифицировать информацию об объектах и классах во время выполнения, и есть два основных способа: одним из них является традиционный RTTI, который предполагает, что мы уже знаем всю информацию о компиляции; Другим является механизм отражения, который позволяет нам открывать и использовать информацию о классах во время выполнения .
1. Классный объект
Чтобы понять, как работает RTTI в Java, вам сначала нужно знать, как информация о типе представлена во время выполнения. Это делается классовыми объектами, которые содержат информацию, связанную с классами. Объекты класса используются для создания всех «обычных» объектов. Java использует объекты класса для выполнения RTTI, даже если вы выполняете операции, такие как преобразование типа.
Каждый класс будет генерировать соответствующий объект класса, который сохраняется в файле .class. Все классы динамически загружаются в JVM, когда они используются в первый раз. Этот класс будет загружен, когда программа создает ссылку на статический член класса. Объекты класса загружаются только при необходимости, и статическая инициализация выполняется при загрузке класса.
открытый класс testmain {public static void main (string [] args) {system.out.println (xyz.name);}} класс XYZ {public Static String name = "luoxn28"; Static {System.out.println ("xyz Static Block");}} public xyz () {System. построен ");}}Результатом вывода:
Загрузчик класса сначала проверяет, был ли загружен объект класса этого класса. Если он не был загружен, загрузчик класса по умолчанию будет искать соответствующий файл .class на основе имени класса.
Чтобы использовать информацию типа во время выполнения, вы должны получить ссылку на объект класса объекта (например, базовый объект). Вы можете использовать функцию class.forname («база») для достижения этого или использовать base.class. Обратите внимание, что это интересно. При использовании функции «.class» для создания ссылки на объект класса объект класса не будет автоматически инициализирован, а использование ForName () автоматически инициализирует объект класса. Приготовления к использованию классов обычно имеют следующие 3 шага:
• Загрузка: заполнена загрузчиком класса, найдите соответствующий байт -код и создайте объект класса
• Ссылка: проверьте байт -код в классе и распределите пространство для статического домена
• Инициализация: если класс имеет суперкласс, он инициализируется, и выполняется статический инициализатор и статическая инициализация.
Общедоступный класс {static int num = 1; static {system.out.println ("base" + num);}} открытый класс main {public static void main (string [] args) {// Статические блоки не будут инициализированным классом clazz1 = base.class; system.out.println ("-----"); Class.forname ("zzz.base");}} 2. Проверьте перед преобразованием типа
Компилятор проверит, является ли тип нисходящего перехода законным, и если он не является законным, будет брошено исключение. Прежде чем преобразовать тип вниз, вы можете использовать экземпляр для суждения.
База класса {} класс полученных расширений extends base {} public class main {public static void main (string [] args) {base base = new Devived (); if (базовый экземпляр defrived) {// здесь вы можете вниз по системе. 3. Отражение: информация о выполнении выполнения
Если вы не знаете точный тип объекта, RTTI может сказать вам, но есть предпосылка: этот тип должен быть известен во время компиляции, чтобы RTTI можно было использовать для его идентификации. Класс класса поддерживает отражение вместе с библиотекой класса java.lang.reflect. Эта библиотека классов содержит классы полевых, методов и конструкторов. Объекты этих классов создаются JVM в стартапе, чтобы представлять соответствующих участников в неизвестных классах. Таким образом, вы можете использовать контракт -конструктор для создания нового объекта, использовать методы get () и set () для получения и изменения поля, связанных с объектом поля в классе, и использовать метод Invoke (), чтобы вызвать метод, связанный с объектом метода. Кроме того, многие удобные методы, такие как getFields (), getMethods () и getConstructors (), также могут быть вызваны для возврата массива, представляющего поля, методы и объекты конструктора. Таким образом, информация о объекте может быть полностью определена во время выполнения, не зная ничего о классе во время компиляции.
В механизме отражения нет ничего волшебного. При работе с объектом неизвестного типа через отражение JVM просто проверяет объект, чтобы увидеть, к какому конкретному классу он принадлежит. Следовательно,. Класс этого класса должен быть получен для JVM, либо на локальной машине, либо из сети. Таким образом, реальная разница между RTTI и отражением только:
• RTTI, компилятор открывает и проверяет.
• Размышлять, открывать и проверить.
Public Class Person реализует serializable {private String name; private int age; // get/set Method} public static void main (string [] args) {Person Person = new Person ("luoxn28", 23); class clazz = person.getClass (); field [] fields = clazz.getDeclaredFields (); для (Field Field: fields = string.getDeclaredFields ();); field.getName (); PropertyDescriptor Descriptor = New PropertyDescriptor (Key, Clazz); Method Method = descriptor.getReadMethod (); object value = method.invoke (человек); system.out.println (key + ":" + value);}}}}}; Приведенный выше вызов функции GET класса через метод getReadMethod (), и метод getWriteMethod () может использоваться для вызова метода SET класса. Вообще говоря, нам не нужно использовать инструменты отражения, но они более полезны в создании динамического кода. Отражение используется в Java для поддержки других функций, таких как сериализация объектов и Javabeans.
4. Динамический агент
Прокси -режим состоит в том, чтобы обеспечить дополнительные или различные операции, а вставленные объекты используются для замены «фактических» объектов, которые включают связь с «фактическими» объектами, поэтому прокси обычно действует как посредник. Динамический прокси Java на шаг впереди идеи прокси, которая может динамически создавать и динамически создавать вызовы к прокси -методам. Все вызовы, сделанные на динамическом прокси, перенаправлены на один процессор вызовов, и его задача состоит в том, чтобы выявить тип вызова и определить соответствующую политику. Вот пример динамического прокси:
Классы интерфейса и реализации:
Интерфейс общедоступного интерфейса {void dosomething (); void comeelse (string arg);} открытый класс Refobject реализует интерфейс {public void dosomething () {System.out.println ("dosomMeething");} public void -vomeelse (string arg) {System.out.println ("Something" + Arg); Динамический процессор объектного объекта динамического прокси:
открытый класс DynamicProxyHandler реализует vocationHandler {private Object Proxyed; public DynamicProxyHandler (Object Proxyed) {this.proxyed = proxyed;}@overridepublic obj Прокси работает. "); return Method.invoke (Proxyed, Args);}} Тестовый класс:
открытый класс main {public static void main (string [] args) {RealObject Real = new RealBject (); интерфейс proxy = (интерфейс) proxy.newproxyinstance (interface.class.getclassloader (), новый класс [] {interface.class}, новый DynamicProxyHandler (Real)); Proxy.dosomething (); Proxy.SomethingElse ("luoxn28");}}Результат вывода заключается в следующем:
Вы можете создать динамический прокси, вызвав прокси -метод Proxy Static Proxy.newProxyInstance (). Этот метод требует загрузчика класса, список интерфейсов, которые вы хотите, чтобы прокси реализовал (не класс или абстрактный класс), и класс реализации vocationHandler. Динамический прокси может перенаправить все вызовы в вызовный процессор, поэтому конструктор процессора вызовов обычно передает ссылку на «фактический» объект, который будет пересылать запрос, когда процессор вызовов выполняет задачу посредничества.
Вышеуказанное-глубокое понимание размышлений о Java, представленном вам редактором. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!