UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

174 lines (166 loc) 19.2 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Object Creation</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Object Creation"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-5-SECT-3"/>Object Creation</h1></div></div></div><p><a id="idx10239" class="indexterm"/> Objects in Java are allocated on a system “heap” memory space. Unlike other languages, however, we needn’t manage that memory ourselves. Java takes care of memory allocation and deallocation for you. Java explicitly allocates storage for an object when you create it with the <a id="I_indexterm5_id692255" class="indexterm"/><code class="literal">new</code> operator. More importantly, objects are removed by garbage collection when they’re no longer referenced.</p><div class="sect2" title="Constructors"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-5-SECT-3.1"/>Constructors</h2></div></div></div><p><a id="idx10240" class="indexterm"/>Objects are allocated with the <code class="literal">new</code> operator using an <span class="emphasis"><em>object constructor</em></span>. A constructor is a special method with the same name as its class and no return type. It’s called when a new class instance is created, which gives the class an opportunity to set up the object for use. Constructors, like other methods, can accept arguments and can be overloaded (they are not, however, inherited like other methods; we’ll discuss inheritance in <a class="xref" href="ch06.html" title="Chapter 6. Relationships Among Classes">Chapter 6</a>).</p><a id="I_5_tt267"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Date</code> <code class="o">{</code> <code class="kt">long</code> <code class="n">time</code><code class="o">;</code> <code class="n">Date</code><code class="o">()</code> <code class="o">{</code> <code class="n">time</code> <code class="o">=</code> <code class="n">currentTime</code><code class="o">();</code> <code class="o">}</code> <code class="n">Date</code><code class="o">(</code> <code class="n">String</code> <code class="n">date</code> <code class="o">)</code> <code class="o">{</code> <code class="n">time</code> <code class="o">=</code> <code class="n">parseDate</code><code class="o">(</code> <code class="n">date</code> <code class="o">);</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>In this example, the class <code class="literal">Date</code> has two constructors. The first takes no arguments; it’s known as the <span class="emphasis"><em>default constructor</em></span>. Default constructors play a special role: if we don’t define any constructors for a class, an empty default constructor is supplied for us. The default constructor is what gets called whenever you create an object by calling its constructor with no arguments. Here we have implemented the default constructor so that it sets the instance variable <code class="literal">time</code> by calling a hypothetical method, <code class="literal">currentTime()</code>, which resembles the functionality of the real <code class="literal">java.util.Date</code> class. The second constructor takes a <code class="literal">String</code> argument. Presumably, this <code class="literal">String</code> contains a string representation of the time that can be parsed to set the <code class="literal">time</code> variable. Given the constructors in the previous example, we create a <code class="literal">Date</code> object in the following ways:</p><a id="I_5_tt268"/><pre class="programlisting"> <code class="n">Date</code> <code class="n">now</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Date</code><code class="o">();</code> <code class="n">Date</code> <code class="n">christmas</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Date</code><code class="o">(</code><code class="s">"Dec 25, 2006"</code><code class="o">);</code></pre><p>In each case, Java chooses the appropriate constructor at compile time based on the rules for overloaded method selection.</p><p>If we later remove all references to an allocated object, it’ll be garbage-collected, as we’ll discuss shortly:</p><a id="I_5_tt269"/><pre class="programlisting"> <code class="n">christmas</code> <code class="o">=</code> <code class="kc">null</code><code class="o">;</code> <code class="c1">// fair game for the garbage collector</code></pre><p>Setting this reference to <code class="literal">null</code> means it’s no longer pointing to the <code class="literal">"Dec 25, 2006"</code> string object. Setting the variable <code class="literal">christmas</code> to any other value would have the same effect. Unless the original string object is referenced by another variable, it’s now inaccessible and can be garbage-collected. We’re not suggesting that you have to set references to <code class="literal">null</code> to get the values garbage-collected. Often this just happens naturally when local variables fall out of scope, but items referenced by instance variables of objects live as long as the object itself lives (through references to it) and static variables live effectively forever.</p><p>A few more notes: constructors can’t be declared <code class="literal">abstract</code>, <code class="literal">synchronized</code>, or <code class="literal">final</code> (we’ll define the rest of those terms later). Constructors can, however, be declared with the visibility modifiers <a id="I_indexterm5_id692459" class="indexterm"/><code class="literal">public</code>, <a id="I_indexterm5_id692474" class="indexterm"/><code class="literal">private</code>, or <a id="I_indexterm5_id692489" class="indexterm"/><code class="literal">protected</code>, just like other methods, to control their accessibility. We’ll talk in detail about visibility modifiers in the next chapter.<a id="I_indexterm5_id692506" class="indexterm"/></p></div><div class="sect2" title="Working with Overloaded Constructors"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-5-SECT-3.2"/>Working with Overloaded Constructors</h2></div></div></div><p><a id="idx10224" class="indexterm"/> <a id="idx10241" class="indexterm"/> <a id="idx10254" class="indexterm"/>A constructor can refer to another constructor in the same class or the immediate superclass using special forms of the <a id="I_indexterm5_id692560" class="indexterm"/><code class="literal">this</code> and <code class="literal">super</code> references. We’ll discuss the first case here and return to that of the superclass constructor after we have talked more about subclassing and inheritance. A constructor can invoke another overloaded constructor in its class using the self-referential method call <code class="literal">this()</code> with appropriate arguments to select the desired constructor. If a constructor calls another constructor, <span class="emphasis"><em>it must do so as its first statement</em></span>:</p><a id="I_5_tt270"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Car</code> <code class="o">{</code> <code class="n">String</code> <code class="n">model</code><code class="o">;</code> <code class="kt">int</code> <code class="n">doors</code><code class="o">;</code> <code class="n">Car</code><code class="o">(</code> <code class="n">String</code> <code class="n">model</code><code class="o">,</code> <code class="kt">int</code> <code class="n">doors</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">model</code> <code class="o">=</code> <code class="n">model</code><code class="o">;</code> <code class="k">this</code><code class="o">.</code><code class="na">doors</code> <code class="o">=</code> <code class="n">doors</code><code class="o">;</code> <code class="c1">// other, complicated setup</code> <code class="o">...</code> <code class="o">}</code> <code class="n">Car</code><code class="o">(</code> <code class="n">String</code> <code class="n">model</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">(</code> <code class="n">model</code><code class="o">,</code> <code class="mi">4</code> <code class="cm">/* doors */</code> <code class="o">);</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>In this example, the class <code class="literal">Car</code> has two constructors. The first, more explicit, one accepts arguments specifying the car’s model and its number of doors. The second constructor takes just the model as an argument and, in turn, calls the first constructor with a default value of four doors. The advantage of this approach is that you can have a single constructor do all the complicated setup work; other auxiliary constructors simply feed the appropriate arguments to that constructor.</p><p>The special call to <code class="literal">this()</code> must appear as the first statement in our delegating constructor. The syntax is restricted in this way because there’s a need to identify a clear chain of command in the calling of constructors. At the end of the chain, Java invokes the constructor of the superclass (if we don’t do it explicitly) to ensure that inherited members are initialized properly before we proceed.</p><p>There’s also a point in the chain, just after invoking the constructor of the superclass, where the initializers of the current class’s instance variables are evaluated. Before that point, we can’t even reference the instance variables of our class. We’ll explain this situation again in complete detail after we have talked about inheritance.</p><p>For now, all you need to know is that you can invoke a second constructor (delegate to it) only as the first statement of your constructor. For example, the following code is illegal and causes a compile-time error:</p><a id="I_5_tt271"/><pre class="programlisting"> <code class="n">Car</code><code class="o">(</code> <code class="n">String</code> <code class="n">m</code> <code class="o">)</code> <code class="o">{</code> <code class="kt">int</code> <code class="n">doors</code> <code class="o">=</code> <code class="n">determineDoors</code><code class="o">();</code> <code class="k">this</code><code class="o">(</code> <code class="n">m</code><code class="o">,</code> <code class="n">doors</code> <code class="o">);</code> <code class="c1">// Error: constructor call</code> <code class="c1">// must be first statement</code> <code class="o">}</code></pre><p>The simple model name constructor can’t do any additional setup before calling the more explicit constructor. It can’t even refer to an instance member for a constant value:</p><a id="I_5_tt272"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Car</code> <code class="o">{</code> <code class="o">...</code> <code class="kd">final</code> <code class="kt">int</code> <code class="n">default_doors</code> <code class="o">=</code> <code class="mi">4</code><code class="o">;</code> <code class="o">...</code> <code class="n">Car</code><code class="o">(</code> <code class="n">String</code> <code class="n">m</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">(</code> <code class="n">m</code><code class="o">,</code> <code class="n">default_doors</code> <code class="o">);</code> <code class="c1">// Error: referencing</code> <code class="c1">// uninitialized variable</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>The instance variable <code class="literal">defaultDoors</code> is not initialized until a later point in the chain of constructor calls setting up the object, so the compiler doesn’t let us access it yet. Fortunately, we can solve this particular problem by using a static variable instead of an instance variable:</p><a id="I_5_tt273"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Car</code> <code class="o">{</code> <code class="o">...</code> <code class="kd">static</code> <code class="kd">final</code> <code class="kt">int</code> <code class="n">DEFAULT_DOORS</code> <code class="o">=</code> <code class="mi">4</code><code class="o">;</code> <code class="o">...</code> <code class="n">Car</code><code class="o">(</code> <code class="n">String</code> <code class="n">m</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">(</code> <code class="n">m</code><code class="o">,</code> <code class="n">DEFAULT_DOORS</code> <code class="o">);</code> <code class="c1">// Okay!</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>The static members of a class are initialized when the class is first loaded into the virtual machine, so it’s safe to access them in a constructor.<a id="I_indexterm5_id692695" class="indexterm"/><a id="I_indexterm5_id692702" class="indexterm"/><a id="I_indexterm5_id692709" class="indexterm"/></p></div><div class="sect2" title="Static and Nonstatic Initializer Blocks"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-5-SECT-3.3"/>Static and Nonstatic Initializer Blocks</h2></div></div></div><p><a id="I_indexterm5_id692723" class="indexterm"/> <a id="I_indexterm5_id692730" class="indexterm"/> <a id="I_indexterm5_id692741" class="indexterm"/>It’s possible to declare a block of code (some statements within curly braces) directly within the scope of a class. This code block doesn’t belong to any method; instead, it’s executed once, at the time the object is constructed, or, in the case of a code block marked <a id="I_indexterm5_id692753" class="indexterm"/><code class="literal">static</code>, at the time the class is loaded. These blocks can be used to do additional setup for the class or an object instance and are called <span class="emphasis"><em>initializer blocks</em></span>.</p><p>Instance initializer blocks can be thought of as extensions of instance variable initialization. They’re called at the time the instance variable’s initializers are evaluated (after superclass construction, but before your constructor body), in the order in which they appear in the Java source:</p><a id="I_5_tt274"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">MyClass</code> <code class="o">{</code> <code class="n">Properties</code> <code class="n">myProps</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Properties</code><code class="o">();</code> <code class="c1">// set up myProps</code> <code class="o">{</code> <code class="n">myProps</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"foo"</code><code class="o">,</code> <code class="s">"bar"</code><code class="o">);</code> <code class="n">myProps</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"boo"</code><code class="o">,</code> <code class="s">"gee"</code><code class="o">);</code> <code class="o">}</code> <code class="kt">int</code> <code class="n">a</code> <code class="o">=</code> <code class="mi">5</code><code class="o">;</code> <code class="o">...</code></pre><p>Normally, this kind of setup could be done just as well in the object’s constructor. A notable exception is in the case of an anonymous inner class (see <a class="xref" href="ch06.html" title="Chapter 6. Relationships Among Classes">Chapter 6</a>).</p><p>Similarly, you can use static initializer blocks to set up static class members. This more useful case allows the static members of a class to have complex initialization just like objects do with constructors:</p><a id="I_5_tt275"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">ColorWheel</code> <code class="o">{</code> <code class="kd">static</code> <code class="n">Hashtable</code> <code class="n">colors</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Hashtable</code><code class="o">();</code> <code class="c1">// set up colors</code> <code class="kd">static</code> <code class="o">{</code> <code class="n">colors</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"Red"</code><code class="o">,</code> <code class="n">Color</code><code class="o">.</code><code class="na">red</code> <code class="o">);</code> <code class="n">colors</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"Green"</code><code class="o">,</code> <code class="n">Color</code><code class="o">.</code><code class="na">green</code> <code class="o">);</code> <code class="n">colors</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"Blue"</code><code class="o">,</code> <code class="n">Color</code><code class="o">.</code><code class="na">blue</code> <code class="o">);</code> <code class="o">...</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>The class <code class="literal">ColorWheel</code> provides a variable, <code class="literal">colors</code>, that maps the names of colors to <code class="literal">Color</code> objects in a <code class="literal">Hashtable</code>. The first time the class <code class="literal">ColorWheel</code> is referenced and loaded, the static components of <code class="literal">ColorWheel</code> are evaluated in the order they appear in the source. In this case, the static code block simply adds elements to the <code class="literal">colors</code> table.<a id="I_indexterm5_id692852" class="indexterm"/></p></div></div></body></html>