UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

177 lines (171 loc) 24.1 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>The Object Class</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="The Object Class"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-7-SECT-1"/>The Object Class</h1></div></div></div><p><code class="literal">java.lang.Object</code> is the ancestor of all objects; it’s the primordial class from which all other classes are ultimately derived. Methods defined in <code class="literal">Object</code> are, therefore, very important because they appear in every instance of every class, throughout all of Java. At last count, there were nine public methods and two protected methods in <code class="literal">Object</code>. Five of these are versions of <code class="literal">wait()</code> and <code class="literal">notify()</code> that are used to synchronize threads on object instances, as we’ll discuss in <a class="xref" href="ch09.html" title="Chapter 9. Threads">Chapter 9</a>. The remaining four methods are used for basic comparison, conversion, and administration.</p><p>Every object has a <a id="I_indexterm7_id701926" class="indexterm"/><code class="literal">toString()</code> method that can be called when it’s to be represented as a text value. <code class="literal">PrintStream</code> objects use <code class="literal">toString()</code> to print data, as discussed in <a class="xref" href="ch12.html" title="Chapter 12. Input/Output Facilities">Chapter 12</a>. <code class="literal">toString()</code> is also used implicitly when an object is referenced in a string concatenation. Here are some examples:</p><a id="I_7_tt357"/><pre class="programlisting"> <code class="n">MyObj</code> <code class="n">myObject</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MyObj</code><code class="o">();</code> <code class="n">Answer</code> <code class="n">theAnswer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Answer</code><code class="o">();</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">myObject</code> <code class="o">);</code> <code class="n">String</code> <code class="n">s</code> <code class="o">=</code> <code class="s">"The answer is: "</code> <code class="o">+</code> <code class="n">theAnswer</code> <code class="o">;</code></pre><p>To be friendly, a new kind of object can override <code class="literal">toString()</code> and implement its own version that provides appropriate information about itself. This is particularly helpful in debugging, where it is common to print the string value of an object to see what is going on. Two other methods, <code class="literal">equals()</code> and <code class="literal">hashCode()</code>, may also require specialization when you create a new class.</p><div class="sect2" title="Equality and Equivalence"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-1.1"/>Equality and Equivalence</h2></div></div></div><p><a id="idx10355" class="indexterm"/> <a id="idx10365" class="indexterm"/> <a id="idx10368" class="indexterm"/> <a id="idx10374" class="indexterm"/> <code class="literal">equals()</code> determines whether two objects are equivalent. Precisely what that means for a particular class is something that you’ll have to decide for yourself. Two <code class="literal">String</code> objects, for example, are considered equivalent if they hold precisely the same characters in the same sequence:</p><a id="I_7_tt358"/><pre class="programlisting"> <code class="n">String</code> <code class="n">userName</code> <code class="o">=</code> <code class="s">"Joe"</code><code class="o">;</code> <code class="o">...</code> <code class="k">if</code> <code class="o">(</code> <code class="n">userName</code><code class="o">.</code><code class="na">equals</code><code class="o">(</code> <code class="n">suspectName</code> <code class="o">)</code> <code class="o">)</code> <code class="n">arrest</code><code class="o">(</code> <code class="n">userName</code> <code class="o">);</code></pre><p>Using <code class="literal">equals()</code> is <a id="I_indexterm7_id702088" class="indexterm"/><span class="emphasis"><em>not</em></span> the same as the “==” operator in Java:</p><a id="I_7_tt359"/><pre class="programlisting"> <code class="k">if</code> <code class="o">(</code> <code class="n">userName</code> <code class="o">==</code> <code class="n">suspectName</code> <code class="o">)</code> <code class="c1">// Wrong!</code></pre><p>This statement tests whether the two reference variables, <code class="literal">userName</code> and <code class="literal">suspectName</code>, refer to the same object. It is a test for <span class="emphasis"><em>identity</em></span>, not equality. Two variables that are identical (point to the same object) will necessarily be equal, but the converse is not always true. It is possible in Java to construct two <code class="literal">String</code> objects with the same contents that are, nonetheless, different instances of the <code class="literal">String</code> class—although, as we’ll describe later, Java tries to help you avoid that when it can.</p><p>A class should override the <code class="literal">equals()</code> method if it needs to implement its own notion of equality. If you have no need to compare objects of a particular class, you don’t necessarily need to override <code class="literal">equals()</code>.</p><p>Watch out for accidentally overloading <code class="literal">equals()</code> if you mean to override it. With overloading, the method signatures differ; with overriding, they must be the same. The <code class="literal">equals()</code> method signature specifies an <code class="literal">Object</code> argument so that an object can be compared to any other kind of object, not only those of its own class type. You’ll probably want to consider only objects of the same type for equivalence. But in order to override (not overload) <code class="literal">equals()</code>, the method must specify its argument to be an <code class="literal">Object</code>.</p><p>Here’s an example of correctly overriding an <code class="literal">equals()</code> method in class <code class="literal">Shoes</code> with an <code class="literal">equals()</code> method in subclass <code class="literal">Sneakers</code>. Using its own method, a <code class="literal">Sneakers</code> object can compare itself with any other object:</p><a id="I_7_tt360"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Sneakers</code> <code class="kd">extends</code> <code class="n">Shoes</code> <code class="o">{</code> <code class="kd">public</code> <code class="kt">boolean</code> <code class="nf">equals</code><code class="o">(</code> <code class="n">Object</code> <code class="n">arg</code> <code class="o">)</code> <code class="o">{</code> <code class="k">if</code> <code class="o">(</code> <code class="o">(</code><code class="n">arg</code> <code class="o">!=</code> <code class="kc">null</code><code class="o">)</code> <code class="o">&amp;&amp;</code> <code class="o">(</code><code class="n">arg</code> <code class="k">instanceof</code> <code class="n">Sneakers</code><code class="o">)</code> <code class="o">)</code> <code class="o">{</code> <code class="c1">// compare arg with this object to check equivalence</code> <code class="c1">// If comparison is okay...</code> <code class="k">return</code> <code class="kc">true</code><code class="o">;</code> <code class="o">}</code> <code class="k">return</code> <code class="kc">false</code><code class="o">;</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>If we specified <code class="literal">public boolean equals(Sneakers arg) ...</code> in the <code class="literal">Sneakers</code> class, we’d overload the <code class="literal">equals()</code> method instead of overriding it. If the other object happens to be assigned to a non-<code class="literal">Sneakers</code> variable, the method signature won’t match. The result: superclass <code class="literal">Shoes</code>’s implementation of <code class="literal">equals()</code> is called, which may or may not be what you intended.<a id="I_indexterm7_id702274" class="indexterm"/><a id="I_indexterm7_id702281" class="indexterm"/><a id="I_indexterm7_id702288" class="indexterm"/><a id="I_indexterm7_id702295" class="indexterm"/></p></div><div class="sect2" title="Hashcodes"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-1.2"/>Hashcodes</h2></div></div></div><p><a id="I_indexterm7_id702309" class="indexterm"/> <a id="idx10366" class="indexterm"/> <a id="idx10369" class="indexterm"/> <a id="I_indexterm7_id702342" class="indexterm"/>The <code class="literal">hashCode()</code> method returns an integer that is a hashcode for the object. A <a id="I_indexterm7_id702358" class="indexterm"/><span class="emphasis"><em>hashcode</em></span> is like a signature or checksum for an object; it’s a random-looking identifying number that is usually generated from the contents of the object. The hashcode should always be different for instances of the class that contain different data, but should be the same for instances that compare “equal” with the <code class="literal">equals()</code> method. Hashcodes are used in the process of storing objects in a <a id="I_indexterm7_id702379" class="indexterm"/><code class="literal">Hashtable</code> or a similar kind of collection. (A <code class="literal">Hashtable</code> is sometimes called a dictionary or associative array in other languages.) A random distribution of the hashcode values helps the <code class="literal">Hashtable</code> optimize its storage of objects by serving as an identifier for distributing them into storage evenly and quickly locating them later.</p><p>The default implementation of <code class="literal">hashCode()</code> in <code class="literal">Object</code> does not really implement this scheme. Instead it assigns each object instance a unique number. If you don’t override this method when you create a subclass, each instance of your class will have a unique hashcode. This is sufficient for some objects. However, if your classes have a notion of equivalent objects (if you have overridden <code class="literal">equals()</code>) and you want equal objects to serve as equivalent keys in a <code class="literal">Hashtable</code>, you should override <code class="literal">hashCode()</code> so that your equivalent objects generate the same hashcode value. We’ll return to the topic of hashcodes in more detail in <a class="xref" href="ch11.html" title="Chapter 11. Core Utilities">Chapter 11</a> when we discuss the <code class="literal">Hashtable</code> and <code class="literal">HashMap</code> classes.<a id="I_indexterm7_id702465" class="indexterm"/><a id="I_indexterm7_id702472" class="indexterm"/></p></div><div class="sect2" title="Cloning Objects"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-7-SECT-1.3"/>Cloning Objects</h2></div></div></div><p><a id="idx10354" class="indexterm"/> <a id="idx10363" class="indexterm"/> <a id="idx10364" class="indexterm"/> <a id="idx10367" class="indexterm"/> <a id="idx10373" class="indexterm"/>Objects can use the <code class="literal">clone()</code> method of the <code class="literal">Object</code> class to make copies of themselves. A copied object is a new object instance, separate from the original. It may or may not contain exactly the same state (the same instance variable values) as the original; that is controlled by the object being copied. Just as important, the decision as to whether the object allows itself to be cloned at all is up to the object.</p><p>The Java <code class="literal">Object</code> class provides the mechanism to make a simple copy of an object including all of its “shallow” state—a <span class="emphasis"><em>bitwise</em></span> copy. But by default, this capability is turned off. (We’ll show why in a moment.) To make itself cloneable, an object must implement the <a id="I_indexterm7_id702577" class="indexterm"/><code class="literal">java.lang.Cloneable</code> interface. This is a flag interface indicating to Java that the object wants to cooperate in being cloned (the interface does not actually contain any methods). If the object isn’t cloneable, the <code class="literal">clone()</code> method throws a <a id="I_indexterm7_id702598" class="indexterm"/><code class="literal">CloneNotSupportedException</code>.</p><p><code class="literal">clone()</code> is a protected method, so by default it can be called only by an object on itself, an object in the same package, or another object of the same type or a subtype. If we want to make an object cloneable by everyone, we have to override its <code class="literal">clone()</code> method and make it public.</p><p>Here is a simple, cloneable class—<code class="literal">Sheep</code>:</p><a id="I_7_tt361"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.util.HashMap</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">Sheep</code> <code class="kd">implements</code> <code class="n">Cloneable</code> <code class="o">{</code> <code class="n">HashMap</code> <code class="n">flock</code> <code class="o">=</code> <code class="k">new</code> <code class="n">HashMap</code><code class="o">();</code> <code class="kd">public</code> <code class="n">Object</code> <code class="nf">clone</code><code class="o">()</code> <code class="o">{</code> <code class="k">try</code> <code class="o">{</code> <code class="k">return</code> <code class="kd">super</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">CloneNotSupportedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="k">throw</code> <code class="k">new</code> <code class="nf">Error</code><code class="o">(</code> <code class="s">"This should never happen because we implement Cloneable!"</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code></pre><p><code class="literal">Sheep</code> has one instance variable, a <code class="literal">HashMap</code> called <code class="literal">flock</code> (which the sheep uses to keep track of its fellow sheep). Our class implements the <code class="literal">Cloneable</code> interface, indicating that it is OK to copy <code class="literal">Sheep</code>, and it has overridden the <code class="literal">clone()</code> method to make it public. Our <code class="literal">clone()</code> simply returns the object created by the superclass’s <code class="literal">clone()</code> method—a copy of our <code class="literal">Sheep</code>. Unfortunately, the compiler is not smart enough to figure out that the object we’re cloning will never throw the <code class="literal">CloneNotSupportedException</code>, so we have to guard against it anyway. Our sheep is now cloneable. We can make copies like so:</p><a id="I_7_tt362"/><pre class="programlisting"> <code class="n">Sheep</code> <code class="n">one</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Sheep</code><code class="o">();</code> <code class="n">Sheep</code> <code class="n">anotherOne</code> <code class="o">=</code> <code class="o">(</code><code class="n">Sheep</code><code class="o">)</code><code class="n">one</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code></pre><p>The cast is necessary here because the return type of <code class="literal">clone()</code> is <code class="literal">Object</code>. We can do better by changing the return type of the overridden <code class="literal">clone()</code> method in the subclass and moving the cast into the <code class="literal">clone()</code> method itself, to make things a little easier on the users of the class:</p><a id="I_7_tt363"/><pre class="programlisting"> <code class="kd">public</code> <code class="n">Sheep</code> <code class="nf">clone</code><code class="o">()</code> <code class="o">{</code> <code class="k">try</code> <code class="o">{</code> <code class="k">return</code> <code class="o">(</code><code class="n">Sheep</code><code class="o">)</code><code class="kd">super</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">CloneNotSupportedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="k">throw</code> <code class="k">new</code> <code class="nf">Error</code><code class="o">(</code><code class="s">"This should never happen!"</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code> <code class="c1">// usage</code> <code class="n">Sheep</code> <code class="n">one</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Sheep</code><code class="o">();</code> <code class="n">Sheep</code> <code class="n">anotherOne</code> <code class="o">=</code> <code class="n">one</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code></pre><p>In either case, we now have two sheep instead of one. A properly implemented <code class="literal">equals()</code> method would tell us that the sheep are equivalent, but <code class="literal">==</code> tells us that they are, in fact, two distinct instances of <a id="I_indexterm7_id702764" class="indexterm"/><code class="literal">Sheep</code>. Java has made a <span class="emphasis"><em>shallow copy</em></span> of our <code class="literal">Sheep</code>. What’s so shallow about it? Java has simply copied the values of our variables. That means that the <code class="literal">flock</code> instance variable in each of our <code class="literal">Sheep</code> still holds the same information—that is, both sheep have a reference to the same <code class="literal">HashMap</code>. The situation looks like that shown in <a class="xref" href="ch07s01.html#learnjava3-CHP-7-FIG-1" title="Figure 7-1. Shallow copy of an object">Figure 7-1</a>.</p><div class="figure"><a id="learnjava3-CHP-7-FIG-1"/><div class="figure-contents"><div class="mediaobject"><a id="I_7_tt364"/><img src="httpatomoreillycomsourceoreillyimages1707627.png" alt="Shallow copy of an object"/></div></div><p class="title">Figure 7-1. Shallow copy of an object</p></div><p>This may or may not be what you intended. If we instead want our <code class="literal">Sheep</code> to have separate copies of its full state (or something in between), we can take control ourselves. In the following example, <code class="literal">DeepSheep</code>, we implement a <span class="emphasis"><em>deep copy</em></span>, duplicating our own <code class="literal">flock</code> variable:</p><a id="I_7_tt365"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">DeepSheep</code> <code class="kd">implements</code> <code class="n">Cloneable</code> <code class="o">{</code> <code class="n">HashMap</code> <code class="n">flock</code> <code class="o">=</code> <code class="k">new</code> <code class="n">HashMap</code><code class="o">();</code> <code class="kd">public</code> <code class="n">DeepSheep</code> <code class="nf">clone</code><code class="o">()</code> <code class="o">{</code> <code class="k">try</code> <code class="o">{</code> <code class="n">DeepSheep</code> <code class="n">copy</code> <code class="o">=</code> <code class="o">(</code><code class="n">DeepSheep</code><code class="o">)</code><code class="kd">super</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="n">copy</code><code class="o">.</code><code class="na">flock</code> <code class="o">=</code> <code class="o">(</code><code class="n">HashMap</code><code class="o">)</code><code class="n">flock</code><code class="o">.</code><code class="na">clone</code><code class="o">();</code> <code class="k">return</code> <code class="n">copy</code><code class="o">;</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">CloneNotSupportedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="k">throw</code> <code class="k">new</code> <code class="nf">Error</code><code class="o">(</code><code class="s">"This should never happen!"</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code></pre><p>Our <code class="literal">clone()</code> method now clones the <code class="literal">HashMap</code> as well. Now, when a <code class="literal">DeepSheep</code> is cloned, the situation looks more like that shown in <a class="xref" href="ch07s01.html#learnjava3-CHP-7-FIG-2" title="Figure 7-2. Deep copy of an object">Figure 7-2</a>.</p><p>Each <code class="literal">DeepSheep</code> now has its own full copy of the map, which can contain different elements. You can see now why objects are not cloneable by default. It would make no sense to assume that all objects can be sensibly duplicated with a shallow copy. Likewise, it makes no sense to assume that a deep copy is necessary, or even correct. In this case, we probably don’t need a deep copy; the flock contains the same members no matter which sheep you’re looking at, so there’s no need to copy the <code class="literal">HashMap</code>. But the decision depends on the object itself and its requirements.</p><div class="figure"><a id="learnjava3-CHP-7-FIG-2"/><div class="figure-contents"><div class="mediaobject"><a id="I_7_tt366"/><img src="httpatomoreillycomsourceoreillyimages1707628.png" alt="Deep copy of an object"/></div></div><p class="title">Figure 7-2. Deep copy of an object</p></div><p>The last method of <code class="literal">Object</code> we need to discuss is <code class="literal">getClass()</code>. This method returns a reference to the <code class="literal">Class</code> object that produced the <code class="literal">Object</code> instance. We’ll talk about it next.<a id="I_indexterm7_id702953" class="indexterm"/><a id="I_indexterm7_id702960" class="indexterm"/><a id="I_indexterm7_id702967" class="indexterm"/><a id="I_indexterm7_id702974" class="indexterm"/><a id="I_indexterm7_id702981" class="indexterm"/></p></div></div></body></html>