Что приведет к инициализации класса Java? - PullRequest
1 голос
/ 26 августа 2011

Я использую метод Wrapper Class , чтобы позволить мне обрабатывать класс, существующий или нет.При использовании этого метода важно знать, что приведет к инициализации моего Proxy класса.В частности, что если I:

  1. Объявить экземпляр Proxy, не задавая для него ничего

    public class myClass {... Proxy myInst;}

  2. Объявление экземпляра Proxy локально внутри оператора никогда не запускаться, если

    public void myMeth {if (ProxyIsAvailableWhichItIsNot) {Proxy myInst;...}}

Обновление: Как отметил Хеннинг, меня интересует, когда класс инициализируется (и запускаются статические блоки), а не когда он загружается.Я обновил вопрос, чтобы отразить это.

Ответы [ 3 ]

2 голосов
/ 26 августа 2011

Реализация Java имеет выбор: загрузка класса, как только другой класс, который ссылается на него, загружен , или откладывание этого до тех пор, пока не возникнет необходимость initialize класс. В первом случае класс может сидеть в течение значительного времени (возможно, навсегда), будучи загруженным , но не инициализированным .

Напротив, существуют точные правила, когда класс инициализируется (запускаются статические инициализаторы), а именно, при первом создании объекта класса или при вызове статического метода, или не постоянное статическое поле доступно.

Единственный полностью надежный способ предотвратить попытки JVM загрузить класс - это не упомянуть об этом явно в коде и использовать Class.forName() и отражение для запроса загрузки в определенный момент времени, в это время ClassNotFoundException может быть брошено и обработано. Однако современные JVM обычно загружают классы гораздо более лениво, чем позволяет языковая спецификация, поэтому на практике часто будут работать более оптимистичные стратегии.

Метод «класс-обертка», описанный в вашей ссылке, не гарантированно будет работать в Java (см. §12.1.2 Спецификации языка Java, 3-е издание), но вполне возможно, что Android / Dalvik дает более строгие гарантии своей собственной .

2 голосов
/ 26 августа 2011

Если вы используете технику, указанную в этом URL-адресе, часть этой техники заключается в вызове статического метода для проверки, загружается ли класс с текущими API или нет.Это позволяет вам сделать что-то вроде этого:

  1. Создать логическое значение, такое как IsMyProxyAvailable
  2. Вызвать статический метод checkAvailable () для вашего прокси-класса
  3. Setзначение true, когда метод завершается успешно, false, если только вы не вызываете его.

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

0 голосов
/ 26 августа 2011

Java имеет очень определенный способ загрузки классов. В Java весь код загружается через ClassLoader. Загруженные классом байты хранятся в памяти в течение длины экземпляра ClassLoader, поэтому ваш экземпляр Class будет существовать до тех пор, пока экземпляр ClassLoader выживет. Классы не могут быть перезагружены или переопределены после загрузки, не выбрасывая ClassLoader, который его загрузил. Когда класс загружается ClassLoader, вызываются статические блоки инициализации. Следовательно, загрузка класса в основном совпадает с инициализацией класса.

Что запускает загрузку класса? Если загружен другой класс, который зависит от него. Когда компилятор Java компилирует класс, он записывает в файл класса все квалифицированные имена классов, от которых он зависит. Классы загружаются как можно позже, поэтому обычно это происходит, когда вы создаете их экземпляры в обычных условиях. Однако наличие статических членов заставит их загружаться до загрузки этого класса. Члены экземпляра будут загружены, когда этот класс также будет создан. Если вам нужны подробности этого процесса, прочитайте следующее:

http://www.ibm.com/developerworks/java/library/j-dyn0429/

К счастью, Dalvik VM работает замечательно, как и JVM, потому что Java подробно описывает этот процесс.

При использовании метода Wrapper в статическом инициализаторе, если Class.forName () завершается успешно, не имеет значения, когда вы определяете Proxy (опция 1 или 2), потому что он уже будет загружен. В противном случае родительский класс Wrapper не будет загружен. Так что просто сделайте вариант 1, так как он проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...