📄 chap07.html
字号:
<P> // Pop int, arrayref, push String at arrayref[int],</P>
<P>33 aaload // which is args[1]</P>
<P> // Pop objref to args[1] String, objref of the</P>
<P> // StringBuffer object (there's still another objref</P>
<P> // to this same object on the stack because of the</P>
<P> // dup instruction above), invoke append() method on</P>
<P> // StringBuffer object, passing args[1] as the only</P>
<P> // parameter. append() will return an objref to this</P>
<P> // StringBuffer object, which will be pushed back</P>
<P> // onto the stack.</P>
<P>34 invokevirtual #10 <Method java.lang.StringBuffer append(java.lang.String)</FONT></P>
<P> // Pop objref to StringBuffer (pushed by append()),</P>
<P> // invoke toString() on it, which returns the value</P>
<P> // of the StringBuffer as a String object. Push</P>
<P> // objref of String object.</P>
<P>37 invokevirtual #13 <Method java.lang.String toString()</FONT></P>
<P>// The string concatenation operation is now complete</P>
<P> </P>
<P> // Pop objref of concatenated String, objref of</P>
<P> // System.out that was pushed by the getstatic</P>
<P> // instruction at offset 15. Invoke println() on</P>
<P> // System.out, passing the concatenated String as</P>
<P> // the only parameter.</P>
<P>40 invokevirtual #12 <Method void println(java.lang.String)</FONT></P>
<P>43 return // Return void from main()</P>
</FONT><FONT SIZE="2"><P> </P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>The bytecodes for <FONT FACE="Courier New">Example5</FONT>韘 <FONT FACE="Courier New">main()</FONT> method contain three implicitly generated <FONT FACE="Courier New">String</FONT> objects and one implicitly generated <FONT FACE="Courier New">StringBuffer</FONT> object. References to two of the <FONT FACE="Courier New">String</FONT> objects appear as arguments passed to <FONT FACE="Courier New">main()</FONT> in the <FONT FACE="Courier New">args</FONT> array, which are pushed onto the stack by the <FONT FACE="Courier New">aaload</FONT> instructions at offset 23 and 33. The <FONT FACE="Courier New">StringBuffer</FONT> is created with the <FONT FACE="Courier New">new</FONT> instruction at offset 18 and initialized with the <FONT FACE="Courier New">invokespecial</FONT> instruction at offset 28. The final <FONT FACE="Courier New">String</FONT>, which represents the concatenation of <FONT FACE="Courier New">args[0]</FONT> and <FONT FACE="Courier New">args[1]</FONT>, is created by calling <FONT FACE="Courier New">toString()</FONT> on the <FONT FACE="Courier New">StringBuffer</FONT> object via the <FONT FACE="Courier New">invokevirtual</FONT> instruction at offset 37.</P>
<P>When the Java Virtual Machine creates a new instance of a class, either implicitly or explicitly, it first allocates memory on the heap to hold the object韘 instance variables. Memory is allocated for all variables declared in the object韘 class and in all its superclasses, including instance variables that are hidden. As described in Chapter 5, "The Java Virtual Machine," memory for other implementation-dependent components of an object韘 image on the heap, such as a pointer to class data in the method area, are also likely allocated at this point. As soon as the virtual machine has set aside the heap memory for a new object, it immediately initializes the instance variables to default initial values. These are the same values shown above in Table 7-1 as default initial values for class variables.</P>
<P>Once the virtual machine has allocated memory for the new object and initialized the instance variables to default values, it is ready to give the instance variables their proper initial values. The Java Virtual Machine uses two techniques to do this, depending upon whether the object is being created because of a <FONT FACE="Courier New">clone()</FONT> invocation. If the object is being created because of a <FONT FACE="Courier New">clone()</FONT>, the virtual machine copies the values of the instance variables of the object being cloned into the new object. Otherwise, the virtual machine invokes an <I>instance initialization method</I> on the object. The instance initialization method initializes the object韘 instance variables to their proper initial values.</P>
<P>The Java compiler generates at least one instance initialization method for every class it compiles. In the Java class file, the instance initialization method is named "<FONT FACE="Courier New"><init</FONT>." For each constructor in the source code of a class, the Java compiler generates one <FONT FACE="Courier New"><init</FONT>()</FONT> method. If the class declares no constructors explicitly, the compiler generates a default no-arg constructor that just invokes the superclass韘 no-arg constructor. As with any other constructor, the compiler creates an <FONT FACE="Courier New"><init</FONT>()</FONT> method in the class file that corresponds to this default constructor.</P>
<P>An <FONT FACE="Courier New"><init</FONT>()</FONT> method can contain three kinds of code: an invocation of another <FONT FACE="Courier New"><init</FONT>()</FONT> method, code that implements any instance variable initializers, and code for the body of the constructor. If a constructor begins with an explicit invocation of another constructor in the same class (a <FONT FACE="Courier New">this()</FONT> invocation) its corresponding <FONT FACE="Courier New"><init</FONT>()</FONT> method will be composed of two parts:</P>
<UL><LI> an invocation of the same-class <FONT FACE="Courier New"><init</FONT>()</FONT> method
<LI> the bytecodes that implement the body of the corresponding constructor</UL>
<P>If a constructor does not begin with a <FONT FACE="Courier New">this()</FONT> invocation and the class is not <FONT FACE="Courier New">Object</FONT>, the <FONT FACE="Courier New"><init</FONT>()</FONT> method will have three components:</P>
<UL><LI> an invocation of a superclass <FONT FACE="Courier New"><init</FONT>()</FONT> method
<LI> the bytecodes for any instance variable initializers
<LI> the bytecodes that implement the body of the corresponding constructor</UL>
<P>If a constructor does not begin with a <FONT FACE="Courier New">this()</FONT> invocation and the class <I>is</I> <FONT FACE="Courier New">Object</FONT>, the first component in the above list is missing. Because <FONT FACE="Courier New">Object</FONT> has no superclass, its <FONT FACE="Courier New"><init</FONT>()</FONT> method韘 can韙 begin with a superclass <FONT FACE="Courier New"><init</FONT>()</FONT> method invocation.</P>
<P>If a constructor begins with an explicit invocation of a superclass constructor ( a <FONT FACE="Courier New">super()</FONT> invocation), its <FONT FACE="Courier New"><init</FONT>()</FONT> method will invoke the corresponding superclass <FONT FACE="Courier New"><init</FONT>()</FONT> method. For example, if a constructor begins with an explicit invocation of the "<FONT FACE="Courier New">super(int, String)</FONT> constructor," the corresponding <FONT FACE="Courier New"><init</FONT>()</FONT> method will begin by invoking the superclass韘 "<FONT FACE="Courier New"><init</FONT>(int, String)</FONT>" method. If a constructor does not begin with an explicit <FONT FACE="Courier New">this()</FONT> or <FONT FACE="Courier New">super()</FONT> invocation, the corresponding <FONT FACE="Courier New"><init</FONT>()</FONT> method will invoke the superclass韘 no-arg <FONT FACE="Courier New"><init</FONT>()</FONT> method by default.</P>
<P>Here韘 an example with three constructors, numbered one through three:</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/ex6/Example6.java
<P>class Example6 {</P>
<P> </P>
<P> private int width = 3;</P>
<P> </P>
<P> // Constructor one:</P>
<P> // This constructor begins with a this() constructor invocation,</P>
<P> // which gets compiled to a same-class <init</FONT>() method</P>
<P> // invocation.</P>
<P> Example6() {</P>
<P> this(1);</P>
<P> System.out.println("Example6(), width = " + width);</P>
<P> }</P>
<P> </P>
<P> // Constructor two:</P>
<P> // This constructor begins with no explicit invocation of another</P>
<P> // constructor, so it will get compiled to an <init</FONT>() method</P>
<P> // that begins with an invocation of the superclass's no-arg</P>
<P> // <init</FONT>() method.</P>
<P> Example6(int width) {</P>
<P> this.width = width;</P>
<P> System.out.println("Example6(int), width = " + width);</P>
<P> }</P>
<P> </P>
<P> // Constructor three:</P>
<P> // This constructor begins with super(), an explicit invocation</P>
<P> // of the superclass's no-arg constructor. Its <init</FONT>() method</P>
<P> // will begin with an invocation of the superclass's no-arg</P>
<P> // <init</FONT>() method.</P>
<P> Example6(String msg) {</P>
<P> super();</P>
<P> System.out.println("Example6(String), width = " + width);</P>
<P> System.out.println(msg);</P>
<P> }</P>
<P> </P>
<P> public static void main(String[] args) {</P>
<P> String msg</P>
<P> = "The Agapanthus is also known as Lilly of the Nile.";</P>
<P> Example6 one = new Example6();</P>
<P> Example6 two = new Example6(2);</P>
<P> Example6 three = new Example6(msg);</P>
<P> }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P> </P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>When executed, the <FONT FACE="Courier New">Example6</FONT> application prints this output:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">Example6(int), width = 1
<P>Example6(), width = 1</P>
<P>Example6(int), width = 2</P>
<P>Example6(String), width = 3</P>
<P>The Agapanthus is also known as Lilly of the Nile.</P>
</FONT><FONT SIZE="2"><P> </P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>The bytecodes for <FONT FACE="Courier New">Example6</FONT>韘 no-arg <FONT FACE="Courier New"><init</FONT>()</FONT> method (the <FONT FACE="Courier New"><init</FONT>()</FONT> method that corresponds to constructor one) are:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// The first component, the same-class <init</FONT>() invocation, begins
<P>// here:</P>
<P> 0 aload_0 // Push the objref from loc var 0 (this)</P>
<P> 1 iconst_1 // Push int constant 1</P>
<P> // Pop int and objref, invoke <init</FONT>() method on</P>
<P> // objref (this), passing the int (a 1) as the</P>
<P> // only parameter.</P>
<P> 2 invokespecial #12 <Method Example6(int)</FONT></P>
<P> </P>
<P>// The second component, the body of the constructor, begins</P>
<P>// here:</P>
<P> // Push objref from System.out</P>
<P> 5 getstatic #16 <Field java.io.PrintStream out</FONT></P>
<P> // Allocate mem for new StringBuffer object, and</P>
<P> // initialize mem to default initial values, push</P>
<P> // objref to new object</P>
<P> 8 new #8 <Class java.lang.StringBuffer</FONT></P>
<P>11 dup // Duplicate objref to StringBuffer object</P>
<P> // Push objref to String literal from constant pool</P>
<P>12 ldc #1 <String "Example6(), width = "</FONT></P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -