⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap07.html

📁 Inside the java virtualMachine,深入研究java虚拟机
💻 HTML
📖 第 1 页 / 共 5 页
字号:
</FONT><FONT SIZE="2"><P>&nbsp;</P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>The <FONT FACE="Courier New">getstatic</FONT> instruction at offset zero uses a symbolic reference (in constant pool entry nine) to the <FONT FACE="Courier New">size</FONT> field of class <FONT FACE="Courier New">Example1a</FONT>. The <FONT FACE="Courier New">bipush</FONT> instruction at offset six is followed by a byte that contains the constant value represented by <FONT FACE="Courier New">Example1d.length</FONT>. <FONT FACE="Courier New">Example1e</FONT>韘 constant pool contains no symbolic reference to anything in class <FONT FACE="Courier New">Example1d</FONT>.</P>
<P>Interfaces may also be awarded a <FONT FACE="Courier New">&lt;clinit</FONT>()</FONT> method in the class file. All fields declared in an interface are implicitly public, static, and final and must be initialized with a field initializer. If an interface has any field initializers that don韙 resolve at compile-time to a constant, that interface will have a <FONT FACE="Courier New">&lt;clinit</FONT>()</FONT> method. Here韘 an example:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex1/Example1f.java
<P>interface Example1f {</P>
<P>&nbsp;</P>
<P>    int ketchup = 5;</P>
<P>    int mustard = (int) (Math.random() * 5.0);</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>The Java compiler generates the following <FONT FACE="Courier New">&lt;clinit</FONT>()</FONT> method for interface <FONT FACE="Courier New">Example1f</FONT>:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// The code for mustard's class variable initializer begins here
<P>                          // Invoke Math.random(), which will push</P>
<P>                          // a double return value</P>
<P> 0 invokestatic #6 &lt;Method double random()</FONT></P>
<P> 3 ldc2_w #7 &lt;Double 5.0</FONT> // Push double constant 2.0</P>
<P> 6 dmul                   // Pop two doubles, multiply, push result</P>
<P> 7 d2i                    // Pop double, convert to int, push int</P>
<P>                          // Pop int, store into class variable</P>
<P>                          // mustard</P>
<P> 8 putstatic #5 &lt;Field int mustard</FONT></P>
<P>11 return                 // Return void from &lt;clinit</FONT> method</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>Note that only the <FONT FACE="Courier New">mustard</FONT> field is initialized by this <FONT FACE="Courier New">&lt;clinit</FONT>()</FONT> method. Because the <FONT FACE="Courier New">ketchup</FONT> field is initialized to a compile-time constant, it is treated specially by the compiler. Although types that use <FONT FACE="Courier New">Example1f.mustard</FONT> will contain a symbolic reference to the field, types that use <FONT FACE="Courier New">Example1f.ketchup</FONT> will contain a local copy of <FONT FACE="Courier New">ketchup</FONT>韘 constant value, 5.</P>
<P><H4><EM>Active versus Passive Use</P></EM></H4>
<P>As mentioned above, the Java Virtual Machine initializes types on their first active use or, in the case of classes, upon the first active use of a subclass. Only four activities constitute an active use: invoking a class initialization method on a new instance of a class, creating an array whose element type is the class, invoking a method declared in a class, and accessing a non-constant field declared in a class or interface.</P>
<P>A use of a non-constant field is an active use of only the class or interface that actually declares the field. For example, a field declared in a class may be referred to via a subclass. A field declared in an interface may be referred to via a subinterface or class that implements the interface. These are passive uses of the subclass, subinterface, or class that implements the interface--uses that won韙 trigger their initialization. They are an active use only of the class or interface in which the field is actually declared. Here韘 an example that illustrates this principle:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex2/NewParent.java
<P>class NewParent {</P>
<P>&nbsp;</P>
<P>    static int hoursOfSleep = (int) (Math.random() * 3.0);</P>
<P>&nbsp;</P>
<P>    static {</P>
<P>        System.out.println("NewParent was initialized.");</P>
<P>    }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex2/NewbornBaby.java
<P>class NewbornBaby extends NewParent {</P>
<P>&nbsp;</P>
<P>    static int hoursOfCrying = 6 + (int) (Math.random() * 2.0);</P>
<P>&nbsp;</P>
<P>    static {</P>
<P>        System.out.println("NewbornBaby was initialized.");</P>
<P>    }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex2/Example2.java
<P>class Example2 {</P>
<P>&nbsp;</P>
<P>    // Invoking main() is an active use of Example2</P>
<P>    public static void main(String[] args) {</P>
<P>&nbsp;</P>
<P>        // Using hoursOfSleep is an active use of Parent, but a</P>
<P>        // passive use of NewbornBaby</P>
<P>        int hours = NewbornBaby.hoursOfSleep;</P>
<P>        System.out.println(hours);</P>
<P>    }</P>
<P>&nbsp;</P>
<P>    static {</P>
<P>        System.out.println("Example2 was initialized.");</P>
<P>    }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>In the above example, executing <FONT FACE="Courier New">main()</FONT> of <FONT FACE="Courier New">Example2</FONT> causes only <FONT FACE="Courier New">Example2</FONT> and <FONT FACE="Courier New">Parent</FONT> to be initialized. <FONT FACE="Courier New">NewbornBaby</FONT> is not initialized and need not be loaded. The following text is printed to the standard output:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT FACE="Courier New"><P>Example2 was initialized.</P>
<P>NewParent was initialized.</P>
<P>2</P>
</FONT><P><FONT FACE="Courier New">end</FONT></P></PRE>
<P>A use of a field that is both <FONT FACE="Courier New">static</FONT> and <FONT FACE="Courier New">final</FONT>, and initialized by a compile-time constant expression, is not an active use of the type that declares the field. As mentioned above, the Java compiler resolves references to such fields to a local copy of the constant value that resides either in the referring classes constant pool, in its bytecode streams, or both. Here韘 an example that illustrates this special treatment of static final fields:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex3/Angry.java
<P>interface Angry {</P>
<P>&nbsp;</P>
<P>    String greeting = "Grrrr!";</P>
<P>&nbsp;</P>
<P>    int angerLevel = Dog.getAngerLevel();</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex3/Dog.java
<P>class Dog {</P>
<P>&nbsp;</P>
<P>    static final String greeting = "Woof, woof, world!";</P>
<P>&nbsp;</P>
<P>    static {</P>
<P>        System.out.println("Dog was initialized.");</P>
<P>    }</P>
<P>&nbsp;</P>
<P>    static int getAngerLevel() {</P>
<P>&nbsp;</P>
<P>        System.out.println("Anger was initialized");</P>
<P>        return 1;</P>
<P>    }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P>&nbsp;</P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file classlife/ex3/Example3.java
<P>class Example3 {</P>
<P>&nbsp;</P>
<P>    // Invoking main() is an active use of Example4</P>
<P>    public static void main(String[] args) {</P>
<P>&nbsp;</P>
<P>        // Using Angry.greeting is a passive use of Angry</P>
<P>        System.out.println(Angry.greeting);</P>
<P>    </P>
<P>&nbsp;</P>
<P>        // Using Dog.greeting is a passive use of Dog</P>
<P>        System.out.println(Dog.greeting);</P>
<P>    }</P>
<P>&nbsp;</P>
<P>    static {</P>
<P>        System.out.println("Example3 was initialized.");</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -