знай это, знай это
0. Предисловие
в предыдущем посте«Размышление от входа до глубокого понимания класса», мы подробно анализируемClassПринцип класса. В этой статье мы анализируемConstructorПринципы использования.
1. Constructor
Есть два способа вызвать конструктор через отражение:
- Вызов конструктора без аргументов:Class.newInstance()
- Вызовите конструктор с параметрами:
- пройти черезClassприобретение классаConstructor
- перечислитьConstructorсерединаnewInstance(Object ... initarges)метод
Для получения подробной информации см.«Отражение от 0 до начала работы», зная это, давайте посмотрим глубжеConstructorсерединаnewInstance(Object ... initarges)метод.
1.1 newInstance
Чтобы понять принцип, сначала нужно понятьjdkПримечания,newInstanceПримечания следующие:
(Извините, я этого не понимаю, вся драма заканчивается...)
Не уходи, я тебе переведу (гугл переводчик действительно ароматный)
Используйте Constructor для представления функции-конструктора, которая создает и инициализирует экземпляр с параметрами. Отдельные параметры автоматически распаковываются, чтобы соответствовать исходным формальным параметрам, а исходные и ссылочные параметры должны быть преобразованы по мере необходимости для вызова метода.
Чтобы получить конструктор без параметров, длина параметра может быть равна 0 или null.
Вызовите нестатический внутренний класс с параметром. . . (здесь не переведено)
И доступ к параметрам через проверку прошел успешно, будем дальше инстанцировать. Если вы объявляете конструктор класса не инициализированным, вам нужно инициализировать
Конструктор завершается, возвращая только что созданный и инициализированный экземпляр
Согласно грубому переводу Сяо Ли, можно получить следующее ключевое содержимое:
- Создайте экземпляр инициализации в соответствии с параметрами, и параметры имеют соответствующие правила;
- Получите конструктор без параметров, длина параметра может быть 0 или null;
- Для доступа и проверки параметров необходимо получить объявленный класс конструктора;
Зная это, давайте интерпретируем этоnewInstance()исходный код, см. следующий рисунок:
Исходный код можно разделить на три части:
- Разрешения на проверку: Разрешения на проверку здесь не анализируются, вы можете просмотреть исходный код самостоятельно.
- Получить объявленный класс конструктора
- Создать сущность
Получить объявленный класс конструктора
класс объявления конструктораConstructorAccessorпредставляет собой интерфейс, как показано на следующем рисунке:
Посмотрите на следующую структуру класса реализации интерфейса (пунктирная линия представляет интерфейс реализации, синяя линия представляет наследование, что за чертовски белая линия?)
Из рисунка видно, что классы реализации наследуютсяConstructorAccessorImplабстрактный класс и реализуетnewInstance() метод.
Итак, какой класс реализации использовать? Давайте продолжать смотреть вниз
еслиConstructorAccessorбыло создано, приобретено и присвоено. пройти, если нетnewConstructorAccessorсоздание методаConstructorAccessor.newConstructorAccessorМетоды, как показано ниже:
newConstructorAccessorДелится на три части:
- Проверить инициализацию
Это фабрика отражений (ReflectionFactory) для проверки состояния инициализации. Если она не инициализирована, она выполнит операцию в красном кружке ниже.
Итак, угадайте, что?
Во-первых, инфляция буквально означает инфляцию или инфляцию, а noInflation буквально не инфляция.
Threshold — это буквально порог, а InflationThreshold — это буквально порог инфляции, который является порогом инфляции.
Согласно буквальному пониманию, noInflation можно использовать для суждения о том, является ли инфляция инфляцией, InflationThreshold — это пороговое значение инфляции.
Попросите Du Niang проверить наши результаты:
JNI (Java Native Interface), используя собственный интерфейс Java для написания программ, может гарантировать, что код может быть легко перенесен на другие платформы.
Как вы можете догадаться, у JVM есть два способа доступа к информации об отраженных классах: либо с помощью средства чтения JNI, либо с помощью средства доступа к байт-коду Java. InflationThreshold — это количество раз, когда используется метод доступа JNI, значение 0 означает, что никогда не читается из метода доступа JNI. Если вы хотите принудительно использовать средства доступа к байт-коду Java, вы можете установить для параметра noInflation значение true.
inflationThresholdЗначение по умолчанию15Если неinflationThresholdмодифицировать,JVMДоступ к отраженной информации класса начинается сJNIаксессор читать15Средства доступа к байт-коду Java не будут использоваться до тех пор, пока
Это может объяснить, почему существует операция обнаружения инициализации.
Из этой части вы можете узнать несколько вещей:
мы можем использовать-D=Чтобы установить системные свойства, получите значение свойства с помощью System.getProperty("Имя свойства").
- Получить экземпляр класса текущего класса
-
Получить при условииConstructorAccessor
Есть так много условий, чтобы судить, не паникуйте, позвольте мне проанализировать волну для вас:
- Первый шаг — проверить, является ли экземпляр класса, полученный на втором шаге, абстрактным классом, и если это абстрактный класс, будет выдано исключение.
- Второй шаг — определить, является ли это экземпляром класса, поскольку конструктор экземпляра класса является закрытым, поэтому этот блок также должен генерировать исключение.
- Шаг 3, определите, наследует ли этот экземпляр классаConstructorAccessorImpl, если это отношения родитель-потомок, вызовитеBootstrapConstructorAccessorImplСоздайтеConstructorAccessor, этот метод должен вызвать собственный метод, базовый собственный интерфейс, реализованный C++.
- Шаг 4, еслиnoInflationверно, а экземпляр класса не является анонимным и должен быть вызванMethodAccessorGenerator.generateConstructor()СоздайтеConstructorAccessorКонкретные детали не проанализированы, принципы или чтение двоичного файла, экземпляры классов загружены, а затем на основе некоторых условий для получения желаемогоConstructor.
- Шаг 5, если ни одно из вышеперечисленных условий не выполняется, позвонитеNativeConstructorAccessorImpl, посмотрите на исходный код этого метода:
звонки иinflationThresholdсравнить, если больше, чемinflationThreshold(По умолчанию 15 раз), вызывается ли метод так же, как и на четвертом шаге.
если меньше или равноinflationThreshold, звонитьnewInstance0метод,newInstance0Это нативный метод, который вызывает локальный интерфейс.
На самом деле, первый шаг инициализации — проложить путь сюда.
Это еще не конец, есть еще одинDelegatingConstructorAccessorImplметод.
Затем эта часть использует режим прокси из первых рук, помещаяNativeConstructorAccessorImplвставитьDelegatingConstructorAccessorImplв делегате . newInstance вызывает метод newInstance делегата.
Я до сих пор помню, когда впервые спросил, что делает белая линия, давайте на этот раз проясним это.
Контента много, нарисую картинку, чтобы показать вам:
Создать экземпляр
полученный на предыдущем шагеConstructorAccessorКласс реализации вызова напрямуюnewInstanceметод создания экземпляра.
2. Резюме
Давайте рассмотрим предыдущий контент:
Сначала мы основываемсяjdkПредоставленные аннотации знаютnewInstanceВы можете инициализировать и вернуть экземпляр по параметрам, для получения экземпляра необходимо получить объявленный класс конструктораConstructorAccessor, а затем мы подробно анализируемConstructorAccessor.
ConstructorAccessorиметь абстрактный классConstructorAccessorImpl, другие классы реализации должны наследоватьConstructorAccessorImpl, которые являются следующими классами реализации:
-
InstantiationExceptionConstructorAccessorImpl: сохранить информацию об исключении, вызватьnewInstanceброситInstantiationExceptionаномальный.
-
BootstrapConstructorAccessorImpl: когда необходимо создать экземпляр класса иConstructorAccessorImplЭто отношения родитель-ребенок, мы собираемся вернутьсяBootstrapConstructorAccessorImpl, который вызывает базовый метод, написанный на C++.
-
SerializationConstructorAccessorImpl: также является абстрактным классом.Когда JVM читает байт-код Java, она возвращает этот класс реализации.
-
NativeConstructorAccessorImpl: вызвать метод локального интерфейса для созданияConstructorAccessor, должен основываться на количестве вызовов иinflationThresholdсравнивать,inflationThresholdЗначение по умолчанию — 15, которое можно изменить с помощью **-Dsun.reflect.inflationThreshold=**.
Когда количество вызовов превышает 15 раз, JVM выбирает из байт-кода Java. Вместо этого получите его из локального интерфейса.
-
DelegatingConstructorAccessorImpl: класс прокси, даNativeConstructorAccessorImplродительский класс.
понятноConstructorAccessor, чтобы создать экземпляр, вызвав метод newInstance().
Статьи, связанные с отражением
«Отражение от 0 до начала работы»
«Размышление от входа до глубокого понимания класса»
Нет публики:Школа знаний Java, который содержит контент, связанный с отражением, который я недавно собрал, я надеюсь, что он может быть полезен для всех.