Кто вызывает метод инициализатора класса и когда?
Я знаю, что новая, dup, invokespecial и Асторе шаблон байт-кода вызовет метод инициализатора экземпляра <init>
когда кто-то экземпляр класса Java с точки зрения языка Java, но я никогда не понимаю, кто вызывает специальный <clinit>
способ и когда это происходит?
Я предполагаю, что <clinit>
вызывается до <init>
метод. Может кто-либо дать мне некоторую информацию доказать? Это задокументировано в спецификации JVM или спецификации языка Java?
3 ответов
спецификация JVM §2.9. Специальные Методы:
класс или интерфейс имеет не более одного метода инициализации класса или интерфейса и инициализируется (§5.5) путем вызова этого метода. Метод инициализации класса или интерфейса имеет специальное имя
<clinit>
, не принимает никаких аргументов, и является недействительным (§4.3.3).имя
<clinit>
поставляется компилятор. Поскольку имя не является допустимым идентификатором, его нельзя использовать непосредственно в написанной программе на языке программирования Java. класса и инициализации методы вызываются неявно виртуальной машиной Java; они никогда не вызываются непосредственно ни от какой инструкции виртуальной машины Java, но вызываются косвенно как часть процесса инициализации класса.
посмотреть Глава 5 для получения дополнительной информации о процессе инициализации класса.
<clinit>
- статический метод, добавленный javac и вызываемый JVM после загрузки класса. Мы можем видеть этот метод в байт-коде класса с инструментами контура байт-кода. Обратите внимание, что <clinit>
добавляется, только если класс нуждается в статической инициализации, e.g
public class Test1 {
static int x = 1;
public static void main(String[] args) throws Exception {
}
}
public class Test2 {
static final int x = 1;
public static void main(String[] args) throws Exception {
}
}
test1 не имеет <clinit>
потому что его поле x
необходимо инициализировать с 1; в то время как Test2 не имеет <clinit>
метод, потому что его x
- константа.
также интересно отметить, что Class.forName
и boolen intialize
param который определяет, должен ли класс быть инициализирован после загрузки или нет.
<clinit>
являются статическими блоками инициализации для класса, а также инициализацией статического поля и его вызовом JVM.
спецификация Java говорит, http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#12174
The initialization method of a class or interface is static and takes no arguments. It has the special name <clinit>. This name is supplied by a compiler. Because the name <clinit> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java virtual machine