Глубокое понимание метода newInstance конструктора

Java

знай это, знай это

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()исходный код, см. следующий рисунок:

Исходный код можно разделить на три части:

  1. Разрешения на проверку: Разрешения на проверку здесь не анализируются, вы можете просмотреть исходный код самостоятельно.
  2. Получить объявленный класс конструктора
  3. Создать сущность

Получить объявленный класс конструктора

класс объявления конструктораConstructorAccessorпредставляет собой интерфейс, как показано на следующем рисунке:

Посмотрите на следующую структуру класса реализации интерфейса (пунктирная линия представляет интерфейс реализации, синяя линия представляет наследование, что за чертовски белая линия?)

Из рисунка видно, что классы реализации наследуютсяConstructorAccessorImplабстрактный класс и реализуетnewInstance() метод.

Итак, какой класс реализации использовать? Давайте продолжать смотреть вниз

еслиConstructorAccessorбыло создано, приобретено и присвоено. пройти, если нетnewConstructorAccessorсоздание методаConstructorAccessor.newConstructorAccessorМетоды, как показано ниже:

newConstructorAccessorДелится на три части:

  1. Проверить инициализацию

Это фабрика отражений (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("Имя свойства").

  1. Получить экземпляр класса текущего класса

  1. Получить при условии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, который содержит контент, связанный с отражением, который я недавно собрал, я надеюсь, что он может быть полезен для всех.