epubjs
Version:
Render ePub documents in the browser, across many devices
174 lines (166 loc) • 19.2 kB
HTML
<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>