epubjs
Version:
Render ePub documents in the browser, across many devices
423 lines (415 loc) • 66.5 kB
HTML
<?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>Subclassing and Inheritance</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="Subclassing and Inheritance"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-6-SECT-1"/>Subclassing and Inheritance</h1></div></div></div><p>Classes in Java exist in a hierarchy. A class in Java can be
declared as a <span class="emphasis"><em>subclass</em></span> of another class using the
<a id="I_indexterm6_id693929" class="indexterm"/><code class="literal">extends</code> keyword. A
subclass <a id="I_indexterm6_id693940" class="indexterm"/><span class="emphasis"><em>inherits</em></span> variables and methods from its
<span class="emphasis"><em>superclass</em></span> and can use them as if they were declared
within the subclass itself:</p><a id="I_6_tt285"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Animal</code> <code class="o">{</code>
<code class="kt">float</code> <code class="n">weight</code><code class="o">;</code>
<code class="o">...</code>
<code class="kt">void</code> <code class="nf">eat</code><code class="o">()</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">Mammal</code> <code class="kd">extends</code> <code class="n">Animal</code> <code class="o">{</code>
<code class="c1">// inherits weight</code>
<code class="kt">int</code> <code class="n">heartRate</code><code class="o">;</code>
<code class="o">...</code>
<code class="c1">// inherits eat()</code>
<code class="kt">void</code> <code class="nf">breathe</code><code class="o">()</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>In this example, an object of type <code class="literal">Mammal</code> has both the instance variable <code class="literal">weight</code> and the method <code class="literal">eat()</code>. They are inherited from <code class="literal">Animal</code>.</p><p>A class can <span class="emphasis"><em>extend</em></span> only one other class. To use
the proper terminology, Java allows <span class="emphasis"><em>single
inheritance</em></span> of class implementation. Later in this chapter,
we’ll talk about interfaces, which take the place of <span class="emphasis"><em>multiple
inheritance</em></span> as it’s primarily used in other languages.</p><p>A subclass can be further subclassed. Normally, subclassing
specializes or refines a class by adding variables and methods (you cannot
remove or hide variables or methods by subclassing). For example:</p><a id="I_6_tt286"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Cat</code> <code class="kd">extends</code> <code class="n">Mammal</code> <code class="o">{</code>
<code class="c1">// inherits weight and heartRate</code>
<code class="kt">boolean</code> <code class="n">longHair</code><code class="o">;</code>
<code class="o">...</code>
<code class="c1">// inherits eat() and breathe()</code>
<code class="kt">void</code> <code class="nf">purr</code><code class="o">()</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>The <code class="literal">Cat</code> class is a type of
<code class="literal">Mammal</code> that is ultimately a type of
<code class="literal">Animal</code>. <code class="literal">Cat</code> objects inherit all the characteristics of
<code class="literal">Mammal</code> objects and, in turn, <code class="literal">Animal</code> objects. <code class="literal">Cat</code> also provides additional behavior in the
form of the <code class="literal">purr()</code> method and the
<code class="literal">longHair</code> variable. We can denote the
class relationship in a diagram, as shown in <a class="xref" href="ch06s01.html#learnjava3-CHP-6-FIG-1" title="Figure 6-1. A class hierarchy">Figure 6-1</a>.</p><p>A subclass inherits all members of its superclass not designated as
<a id="I_indexterm6_id694080" class="indexterm"/><code class="literal">private</code>. As we’ll discuss
shortly, other levels of visibility affect which inherited members of the
class can be seen from outside of the class and its subclasses, but at a
minimum, a subclass always has the same set of visible members as its
parent. For this reason, the type of a subclass can be considered a
<span class="emphasis"><em>subtype</em></span> of its parent, and instances of the subtype
can be used anywhere instances of the supertype are allowed. Consider the
following example:</p><a id="I_6_tt287"/><pre class="programlisting"> <code class="n">Cat</code> <code class="n">simon</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Cat</code><code class="o">();</code>
<code class="n">Animal</code> <code class="n">creature</code> <code class="o">=</code> <code class="n">simon</code><code class="o">;</code></pre><div class="figure"><a id="learnjava3-CHP-6-FIG-1"/><div class="figure-contents"><div class="mediaobject"><a id="I_6_tt288"/><img src="httpatomoreillycomsourceoreillyimages1707619.png" alt="A class hierarchy"/></div></div><p class="title">Figure 6-1. A class hierarchy</p></div><p>The <code class="literal">Cat</code> instance <code class="literal">simon</code> in this example can be assigned to the
<code class="literal">Animal</code> type variable <code class="literal">creature</code> because <code class="literal">Cat</code> is a subtype of <code class="literal">Animal</code>. Similarly, any method accepting an
<code class="literal">Animal</code> object would accept an instance
of a <code class="literal">Cat</code> or any <code class="literal">Mammal</code> type as well. This is an important aspect
of polymorphism in an object-oriented language such as Java. We’ll see how
it can be used to refine a class’s behavior, as well as add new
capabilities to it.</p><div class="sect2" title="Shadowed Variables"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-1.1"/>Shadowed Variables</h2></div></div></div><p><a id="idx10320" class="indexterm"/> <a id="idx10327" class="indexterm"/> <a id="idx10335" class="indexterm"/> <a id="idx10343" class="indexterm"/>In <a class="xref" href="ch05.html" title="Chapter 5. Objects in Java">Chapter 5</a>, we saw that a
local variable of the same name as an instance variable
<span class="emphasis"><em>shadows</em></span> (hides) the instance variable. Similarly,
an instance variable in a subclass can shadow an instance variable of
the same name in its parent class, as shown in <a class="xref" href="ch06s01.html#learnjava3-CHP-6-FIG-2" title="Figure 6-2. The scope of shadowed variables">Figure 6-2</a>. We’re going to cover the details of
this variable hiding now for completeness and in preparation for more
advanced topics, but in practice you should almost never do this. It is
much better in practice to structure your code to clearly differentiate
variables using different names or naming conventions.</p><p>In <a class="xref" href="ch06s01.html#learnjava3-CHP-6-FIG-2" title="Figure 6-2. The scope of shadowed variables">Figure 6-2</a>, the variable
<code class="literal">weight</code> is declared in three places:
as a local variable in the method <code class="literal">foodConsumption()</code> of the class <code class="literal">Mammal</code>, as an instance variable of the class
<code class="literal">Mammal</code>, and as an instance variable
of the class <code class="literal">Animal</code>. The actual
variable selected when you reference it in the code would depend on the
scope in which we are working and how you qualify the reference to
it.</p><div class="figure-float"><div class="figure"><a id="learnjava3-CHP-6-FIG-2"/><div class="figure-contents"><div class="mediaobject"><a id="I_6_tt289"/><img src="httpatomoreillycomsourceoreillyimages1707620.png" alt="The scope of shadowed variables"/></div></div><p class="title">Figure 6-2. The scope of shadowed variables</p></div></div><p>In the previous example, all variables were of the same type. A
slightly more plausible use of shadowed variables would involve changing
their types. We could, for example, shadow an <code class="literal">int</code> variable with a <code class="literal">double</code> variable in a subclass that needs
decimal values instead of integer values. We can do this without
changing the existing code because, as its name suggests, when we shadow
variables, we don’t replace them but instead mask them. Both variables
still exist; methods of the superclass see the original variable, and
methods of the subclass see the new version. The determination of what
variables the various methods see occurs at compile time.</p><p>Here’s a simple example:</p><a id="I_6_tt290"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">IntegerCalculator</code> <code class="o">{</code>
<code class="kt">int</code> <code class="n">sum</code><code class="o">;</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">DecimalCalculator</code> <code class="kd">extends</code> <code class="n">IntegerCalculator</code> <code class="o">{</code>
<code class="kt">double</code> <code class="n">sum</code><code class="o">;</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>In this example, we shadow the instance variable <code class="literal">sum</code> to change its type from <code class="literal">int</code> to <code class="literal">double</code>.<sup>[<a id="learnjava3-CHP-6-FNOTE-1" href="#ftn.learnjava3-CHP-6-FNOTE-1" class="footnote">15</a>]</sup> Methods defined in the class <code class="literal">IntegerCalculator</code> see the integer variable
<code class="literal">sum</code>, while methods defined in
<code class="literal">DecimalCalculator</code> see the
floating-point variable <code class="literal">sum</code>. However,
both variables actually exist for a given instance of <code class="literal">DecimalCalculator</code>, and they can have
independent values. In fact, any methods that <code class="literal">DecimalCalculator</code> inherits from <code class="literal">IntegerCalculator</code> actually see the integer
variable <code class="literal">sum</code>.</p><p>Because both variables exist in <code class="literal">DecimalCalculator</code>, we need a way to reference
the variable inherited from <code class="literal">IntegerCalculator</code>. We do that using the
<a id="I_indexterm6_id694460" class="indexterm"/><code class="literal">super</code> keyword as a
qualifier on the reference:</p><a id="I_6_tt291"/><pre class="programlisting"> <code class="kt">int</code> <code class="n">s</code> <code class="o">=</code> <code class="kd">super</code><code class="o">.</code><code class="na">sum</code><code class="o">;</code></pre><p>Inside of <code class="literal">DecimalCalculator</code>,
the <code class="literal">super</code> keyword used in this manner
selects the <code class="literal">sum</code> variable defined in
the superclass. We’ll explain the use of <code class="literal">super</code> more fully in a bit.</p><p>Another important point about shadowed variables has to do with
how they work when we refer to an object by way of a less derived type
(a parent type). For example, we can refer to a <code class="literal">DecimalCalculator</code> object as an <code class="literal">IntegerCalculator</code> by using it via a variable
of type <code class="literal">IntegerCalculator</code>. If we do
so and then access the variable <code class="literal">sum</code>,
we get the integer variable, not the decimal one:</p><a id="I_6_tt292"/><pre class="programlisting"> <code class="n">DecimalCalculator</code> <code class="n">dc</code> <code class="o">=</code> <code class="k">new</code> <code class="n">DecimalCalculator</code><code class="o">();</code>
<code class="n">IntegerCalculator</code> <code class="n">ic</code> <code class="o">=</code> <code class="n">dc</code><code class="o">;</code>
<code class="kt">int</code> <code class="n">s</code> <code class="o">=</code> <code class="n">ic</code><code class="o">.</code><code class="na">sum</code><code class="o">;</code> <code class="c1">// accesses IntegerCalculator sum</code></pre><p>The same would be true if we accessed the object using an explicit
cast to the <code class="literal">IntegerCalculator</code> type or
when passing an instance into a method that accepts that parent
type.</p><p>To reiterate, the usefulness of shadowed variables is limited.
It’s much better to abstract the use of variables like this in other
ways than to use tricky scoping rules. However, it’s important to
understand the concepts here before we talk about doing the same thing
with methods. We’ll see a different and more dynamic type of behavior
when methods shadow other methods, or to use the correct terminology,
<span class="emphasis"><em>override</em></span> other methods.<a id="I_indexterm6_id694562" class="indexterm"/><a id="I_indexterm6_id694570" class="indexterm"/><a id="I_indexterm6_id694577" class="indexterm"/><a id="I_indexterm6_id694584" class="indexterm"/></p></div><div class="sect2" title="Overriding Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-1.2"/>Overriding Methods</h2></div></div></div><p><a id="idx10319" class="indexterm"/>In <a class="xref" href="ch05.html" title="Chapter 5. Objects in Java">Chapter 5</a>, we saw that we
could declare <span class="emphasis"><em>overloaded methods</em></span> (i.e., methods
with the same name but a different number or type of arguments) within a
class. Overloaded method selection works in the way we described on all
methods available to a class, including inherited ones. This means that
a subclass can define additional overloaded methods that add to the
overloaded methods provided by a superclass.</p><p>A subclass can do more than that; it can define a method that has
exactly the <span class="emphasis"><em>same</em></span> method signature (name and
argument types) as a method in its superclass. In that case, the method
in the subclass <span class="emphasis"><em>overrides</em></span> the method in the
superclass and effectively replaces its implementation, as shown in
<a class="xref" href="ch06s01.html#learnjava3-CHP-6-FIG-3" title="Figure 6-3. Method overriding">Figure 6-3</a>. <a id="I_indexterm6_id694641" class="indexterm"/>Overriding methods to change the behavior of objects is
called <span class="emphasis"><em>subtype polymorphism</em></span>. It’s the usage most
people think of when they talk about the power of object-oriented
languages.</p><div class="figure"><a id="learnjava3-CHP-6-FIG-3"/><div class="figure-contents"><div class="mediaobject"><a id="I_6_tt293"/><img src="httpatomoreillycomsourceoreillyimages1707621.png" alt="Method overriding"/></div></div><p class="title">Figure 6-3. Method overriding</p></div><p>In <a class="xref" href="ch06s01.html#learnjava3-CHP-6-FIG-3" title="Figure 6-3. Method overriding">Figure 6-3</a>, <code class="literal">Mammal</code> overrides the <code class="literal">reproduce()</code> method of <code class="literal">Animal</code>, perhaps to specialize the method for
the behavior of mammals giving birth to live young.<sup>[<a id="learnjava3-CHP-6-FNOTE-2" href="#ftn.learnjava3-CHP-6-FNOTE-2" class="footnote">16</a>]</sup> The <code class="literal">Cat</code> object’s
sleeping behavior is also overridden to be different from that of a
general <code class="literal">Animal</code>, perhaps to
accommodate cat naps. The <code class="literal">Cat</code> class
also adds the more unique behaviors of purring and hunting mice.</p><p>From what you’ve seen so far, overridden methods probably look
like they shadow methods in superclasses, just as variables do. But
overridden methods are actually more powerful than that. When there are
multiple implementations of a method in the inheritance hierarchy of an
object, the one in the “most derived” class (the furthest down the
hierarchy) always overrides the others, even if we refer to the object
through a reference of one of the superclass types.<sup>[<a id="learnjava3-CHP-6-FNOTE-3" href="#ftn.learnjava3-CHP-6-FNOTE-3" class="footnote">17</a>]</sup></p><p>For example, if we have a <code class="literal">Cat</code>
instance assigned to a variable of the more general type <code class="literal">Animal</code>, and we call its <code class="literal">sleep()</code> method, we still get the <code class="literal">sleep()</code> method implemented in the <code class="literal">Cat</code> class, not the one in <code class="literal">Animal</code>:</p><a id="I_6_tt294"/><pre class="programlisting"> <code class="n">Cat</code> <code class="n">simon</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Cat</code><code class="o">();</code>
<code class="n">Animal</code> <code class="n">creature</code> <code class="o">=</code> <code class="n">simon</code><code class="o">;</code>
<code class="o">...</code>
<code class="n">creature</code><code class="o">.</code><code class="na">sleep</code><code class="o">();</code> <code class="c1">// accesses Cat sleep();</code></pre><p>In other words, for purposes of behavior (invoking methods), a
<code class="literal">Cat</code> acts like a <code class="literal">Cat</code>, regardless of whether you refer to it as
such. In other respects, the variable <code class="literal">creature</code> here may behave like an <code class="literal">Animal</code> reference. As we explained earlier,
access to a shadowed variable through an <code class="literal">Animal</code> reference would find an implementation
in the <code class="literal">Animal</code> class, not the <code class="literal">Cat</code> class. However, because methods are
located <span class="emphasis"><em>dynamically</em></span>, searching subclasses first,
the appropriate method in the <code class="literal">Cat</code>
class is invoked, even though we are treating it more generally as an
<code class="literal">Animal</code> object. This means that the
<span class="emphasis"><em>behavior</em></span> of objects is dynamic. We can deal with
specialized objects as if they were more general types and still take
advantage of their specialized implementations of behavior.</p><div class="sect3" title="@Override"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.1"/>@Override</h3></div></div></div><p><a id="I_indexterm6_id694896" class="indexterm"/> <a id="idx10294" class="indexterm"/> <a id="I_indexterm6_id694919" class="indexterm"/> <a id="I_indexterm6_id694930" class="indexterm"/>A common programming error in Java is to accidentally
overload a method when trying to override it. Any difference in the
number or type of arguments (the method
<span class="emphasis"><em>signature</em></span>) produces two overloaded methods
instead of a single, overridden method. The new annotations syntax in
Java 5.0 provides a way to get the compiler to help with this problem.
An annotation, as we’ll describe in <a class="xref" href="ch07.html" title="Chapter 7. Working with Objects and Classes">Chapter 7</a>, allows us to add special markers or
metadata to source code that can be read by the compiler or runtime
tools. One of the standard annotations that Java defines is called
<code class="literal">@Override</code> and it tells the compiler
that the method it marks is intended to override a method in the
superclass. The compiler then warns if the method doesn’t match. For
example, we could specify that the <code class="literal">sleep()</code> method of our <code class="literal">Cat</code> class overrides one in a superclass like
so:</p><a id="I_6_tt295"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Cat</code> <code class="kd">extends</code> <code class="n">Mammal</code> <code class="o">{</code>
<code class="o">...</code>
<code class="nd">@Override</code> <code class="kt">void</code> <code class="n">sleep</code><code class="o">()</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="o">}</code></pre></div><div class="sect3" title="Overridden methods and dynamic binding"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.2"/>Overridden methods and dynamic binding</h3></div></div></div><p><a id="idx10269" class="indexterm"/> <a id="idx10276" class="indexterm"/> <a id="idx10296" class="indexterm"/> <a id="idx10304" class="indexterm"/> <a id="idx10331" class="indexterm"/>In a previous section, we mentioned that
<span class="emphasis"><em>overloaded</em></span> methods are selected by the compiler
at compile time. <span class="emphasis"><em>Overridden</em></span> methods, on the other
hand, are selected dynamically at runtime. Even if we create an
instance of a subclass our code has never seen before (perhaps a new
class loaded over the network), any overriding methods that it
contains are located and used at runtime, replacing those that existed
when we last compiled our code.</p><p>In contrast, if we created a new class that implements an
additional, more specific, overloaded method, and replace the compiled
class in our classpath with it, our code would continue to use the
implementation it discovered originally. This situation would persist
until we recompiled our code along with the new class. Another effect
of this is that casting (i.e., explicitly telling the compiler to
treat an object as one of its assignable types) affects the selection
of overloaded methods at compile time but not overridden
methods.</p><p>In practice what we’ve just described is not something you need
to worry about often, but it’s important in understanding what the
virtual machine does and does not do at runtime.</p></div><div class="sect3" title="Static method binding"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.3"/>Static method binding</h3></div></div></div><p><a id="I_indexterm6_id695091" class="indexterm"/> <a id="I_indexterm6_id695099" class="indexterm"/> <a id="I_indexterm6_id695110" class="indexterm"/> <a id="I_indexterm6_id695119" class="indexterm"/> <a id="I_indexterm6_id695127" class="indexterm"/>Static methods don’t belong to any object instance; they
are accessed directly through a class name, so they are not
dynamically selected at runtime like instance methods. That is why
static methods are called “static”; they are always bound at compile
time.</p><p>A static method in a superclass can be shadowed by another
static method in a subclass, as long as the original method was not
declared final. However, both methods are always accessible directly
via their respective class names. You can’t “override” a static method
with an instance method. In other words, you can’t have a static
method and instance method with the same signature in the same class
hierarchy.</p></div><div class="sect3" title="final methods and performance"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.4"/>final methods and performance</h3></div></div></div><p><a id="I_indexterm6_id695161" class="indexterm"/> <a id="I_indexterm6_id695172" class="indexterm"/> <a id="I_indexterm6_id695181" class="indexterm"/>In languages like C++, the default is for methods to act
like shadowed variables, so you have to declare explicitly the methods
you want to be dynamic (or, as C++ terms them,
<span class="emphasis"><em>virtual</em></span>). In Java, instance methods are, by
default, dynamic. But you can use the <a id="I_indexterm6_id695198" class="indexterm"/><code class="literal">final</code> modifier to
declare that an instance method can’t be overridden in a subclass, and
it won’t be subject to dynamic binding.</p><p>We have seen <code class="literal">final</code> used with
variables to effectively make them constants. When applied to a
method, <code class="literal">final</code> means that its
implementation is constant—no overriding allowed. <code class="literal">final</code> can also be applied to an entire
class, which means the class can’t be subclassed.</p><p>In the old days, dynamic method binding came with a significant
performance penalty, and some people are still inclined to use the
<code class="literal">final</code> modifier to guard against
this. Modern Java runtime systems eliminate the need for this kind of
tweaking. A profiling runtime can determine which methods are not
being overridden and “optimistically” inline them, treating them as if
they were final until it becomes necessary to do otherwise. As a rule,
you should use the <code class="literal">final</code> keyword
when it is correct for your program’s structure, not for performance
considerations.</p></div><div class="sect3" title="Compiler optimizations"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.5"/>Compiler optimizations</h3></div></div></div><p><a id="idx10274" class="indexterm"/> <a id="idx10295" class="indexterm"/> <a id="idx10303" class="indexterm"/> <a id="idx10330" class="indexterm"/>In some older versions of Java, the <a id="I_indexterm6_id695316" class="indexterm"/><span class="emphasis"><em>javac</em></span> compiler can be run with a
<a id="I_indexterm6_id695327" class="indexterm"/><span class="emphasis"><em>-O</em></span> switch, which tells it to
perform certain optimizations, like inlining, statically. Most of
these optimizations are now done at runtime by smarter VMs, so
switches like this are generally not necessary.</p><p>Another kind of optimization allows you to include debugging
code in your Java source without incurring a size or performance
penalty. Although Java doesn’t have a preprocessor to explicitly
control what source is included, you can get some of the same effects
by making a block of code conditional on a constant (i.e., <code class="literal">static</code> and <code class="literal">final</code>) variable. The Java compiler is smart
enough to remove this code when it determines that it won’t be called.
For example:</p><a id="I_6_tt296"/><pre class="programlisting"> <code class="kd">static</code> <code class="kd">final</code> <code class="kt">boolean</code> <code class="n">DEBUG</code> <code class="o">=</code> <code class="kc">false</code><code class="o">;</code>
<code class="o">...</code>
<code class="kd">final</code> <code class="kt">void</code> <code class="nf">debug</code> <code class="o">(</code><code class="n">String</code> <code class="n">message</code><code class="o">)</code> <code class="o">{</code>
<code class="k">if</code> <code class="o">(</code><code class="n">DEBUG</code><code class="o">)</code> <code class="o">{</code>
<code class="n">System</code><code class="o">.</code><code class="na">err</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">message</code><code class="o">);</code>
<code class="c1">// do other stuff</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>In this case, the compiler can recognize that the condition on
the <code class="literal">DEBUG</code> variable is always
<code class="literal">false</code>, and the body of the <code class="literal">debug()</code> method will be optimized away. With
a modern compiler, the method call might even be optimized away
entirely.</p><p>Note that this kind of debugging code is useful for purposes
such as logging. In contrast to assertions, which we covered in <a class="xref" href="ch04.html" title="Chapter 4. The Java Language">Chapter 4</a>, which are supposed to be yes/no tests
that guarantee the correctness of your program logic, these
conditional blocks of code might do expensive formatting or other
output processing that is useful during develoment but you don’t wish
to have around in the final product.<a id="I_indexterm6_id695404" class="indexterm"/><a id="I_indexterm6_id695411" class="indexterm"/><a id="I_indexterm6_id695418" class="indexterm"/><a id="I_indexterm6_id695425" class="indexterm"/></p></div><div class="sect3" title="Method selection revisited"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.6"/>Method selection revisited</h3></div></div></div><p><a id="idx10298" class="indexterm"/> <a id="idx10300" class="indexterm"/> <a id="idx10306" class="indexterm"/> <a id="idx10333" class="indexterm"/>By now you should have a good, intuitive feel for how
methods are selected from the pool of potentially overloaded and
overridden method names of a class. If, however, you are dying for
more detail, we’ll provide it now.</p><p>In a previous section, we offered an inductive rule for
overloaded method resolution. It said that a method is considered more
specific than another if its arguments are assignable to the arguments
of the second method. We can now expand this rule to include the
resolution of overridden methods by adding the following condition: to
be more specific than another method, the type of the class containing
the method must also be assignable to the type of the class holding
the second method.</p><p>What does that mean? Well, the only classes whose types are
assignable are classes in the same inheritance hierarchy, meaning that
we’re talking about the set of all methods of the same name in a class
or any of its parent or child classes. Because subclass types are
assignable to superclass types, but not vice versa, the resolution is
pushed in the way that we expect down the chain toward the subclasses.
This effectively adds a second dimension to the search, in which
resolution is pushed down the inheritance tree toward more refined
classes and, simultaneously, toward the most specific overloaded
method within a given class.</p></div><div class="sect3" title="Exceptions and overridden methods"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.7"/>Exceptions and overridden methods</h3></div></div></div><p><a id="idx10277" class="indexterm"/> <a id="idx10297" class="indexterm"/> <a id="idx10305" class="indexterm"/> <a id="idx10332" class="indexterm"/> <a id="idx10341" class="indexterm"/>An overriding method may change the behavior of an
object, but in some ways, it must still fulfill the contract of the
original method with the user. Specifically, an overriding method must
adhere to the <code class="literal">throws</code> clause of the
original method. The new method cannot throw new types of checked
exceptions. It can only declare that it throws exception types
assignable to those thrown by the method in the parent class; that is,
it may declare that it throws the same types of exceptions or subtypes
of those declared by the original method. If the new method does not
throw any of the checked exceptions of the original, it does not have
to declare them and callers of the method via the subclass do not have
to guard against them. (In this way, you can override a method to
“handle” exceptions for the user.)</p><p>So the new method may declare exactly the same checked
exceptions as the original, or it has the option to refine those types
by declaring that it throws more specific subtypes than the overridden
method. This is not the same as just saying that the method can simply
throw subtypes of its declared exceptions; any method can do that. The
new method can actually redefine the <code class="literal">throws</code> clause of the method to be more
specific. This technique is called <a id="I_indexterm6_id695627" class="indexterm"/><span class="emphasis"><em>covariant</em></span> typing of the <code class="literal">throws</code> clause, which means that the
exception types against which the user must guard change to become
more refined with the subtype.</p><p>Let’s quickly review what the <code class="literal">throws</code> clause really means. If a method
declares that it can throw an <code class="literal">IOException</code>, it is really saying that it can
throw exceptions of type <code class="literal">IOException</code> or its subtypes. For example,
<code class="literal">FileNotFoundException</code> is a type of
<code class="literal">IOException</code>. A method declaring
that it can throw <code class="literal">IOException</code> could
actually throw <code class="literal">FileNotFoundException</code> or any other subtype
of <code class="literal">IOException</code> at runtime:</p><a id="I_6_tt297"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">readFile</code><code class="o">()</code> <code class="kd">throws</code> <code class="n">IOException</code> <code class="o">{</code>
<code class="o">...</code>
<code class="k">if</code> <code class="o">(</code> <code class="n">error</code> <code class="o">)</code> <code class="k">throw</code> <code class="k">new</code> <code class="n">FileNotFoundException</code><code class="o">(</code> <code class="n">filename</code> <code class="o">);</code>
<code class="o">}</code></pre><p>When we call this method, the compiler will ensure that we allow
for the possibility of any kind of <code class="literal">IOException</code>, using either a <code class="literal">try/catch</code> block or by throwing the exception
from our own method.</p><p>When we override a method in a subclass, we get an opportunity
to rewrite the <code class="literal">throws</code> clause of the
method a bit. The new method must still be backward-compatible with
the original, so any checked exceptions it throws must be assignable
to those thrown by the overridden method. But we can be more specific
if we want, refining the type of exception to go along with the new
method’s behavior. For example:</p><a id="I_6_tt298"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">MeatInedibleException</code> <code class="kd">extends</code> <code class="n">InedibleException</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="kd">class</code> <code class="nc">Animal</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">eat</code><code class="o">(</code> <code class="n">Food</code> <code class="n">f</code> <code class="o">)</code> <code class="kd">throws</code> <code class="n">InedibleException</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">Herbivore</code> <code class="kd">extends</code> <code class="n">Animal</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">eat</code><code class="o">(</code> <code class="n">Food</code> <code class="n">f</code> <code class="o">)</code> <code class="kd">throws</code> <code class="n">MeatInedibleException</code> <code class="o">{</code>
<code class="k">if</code> <code class="o">(</code> <code class="n">f</code> <code class="k">instanceof</code> <code class="n">Meat</code> <code class="o">)</code>
<code class="k">throw</code> <code class="k">new</code> <code class="nf">MeatInedibleException</code><code class="o">();</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>In this code, <code class="literal">Animal</code>
specifies that it can throw an <code class="literal">InedibleException</code> from its <code class="literal">eat()</code> method. <code class="literal">Herbivore</code> is a subclass of <code class="literal">Animal</code>, so its <code class="literal">eat()</code> method must also be able to throw an
<code class="literal">InedibleException</code>. However,
<code class="literal">Herbivore</code>’s <code class="literal">eat()</code> method actually declares that it
throws a more specific exception: <code class="literal">MeatInedibleException</code>. It can do this
because <code class="literal">MeatInedibleException</code> is a
subtype of <code class="literal">InedibleException</code>. If we
are working with an <code class="literal">Herbivore</code> type
directly, the compiler will allow us to catch just the <code class="literal">MeatInedibleException</code> and not require us to
guard against the more general <code class="literal">InedibleException</code>:</p><a id="I_6_tt299"/><pre class="programlisting"> <code class="n">Herbivore</code> <code class="n">creature</code> <code class="o">=</code> <code class="o">...</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">creature</code><code class="o">.</code><code class="na">eat</code><code class="o">(</code> <code class="n">food</code> <code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">MeatInedibleException</code> <code class="o">)</code> <code class="o">{</code>
<code class="c1">// creature can't eat this food because it's meat</code>
<code class="o">}</code></pre><p>On the other hand, if we don’t care why the food is inedible,
we’re free to guard for the more general <code class="literal">InedibleException</code> alone and treat it as any
other <code class="literal">Animal</code>.<a id="I_indexterm6_id695857" class="indexterm"/></p><p>To sum up, an overriding method can refine not only the behavior
of the parent method, but also the type of checked exceptions it
throws. Next, we’ll talk about overridden methods that change their
return type in exactly the same way.<a id="I_indexterm6_id695871" class="indexterm"/><a id="I_indexterm6_id695878" class="indexterm"/><a id="I_indexterm6_id695885" class="indexterm"/><a id="I_indexterm6_id695892" class="indexterm"/></p></div><div class="sect3" title="Return types and overridden methods"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-1.2.8"/>Return types and overridden methods</h3></div></div></div><p><a id="idx10299" class="indexterm"/> <a id="idx10307" class="indexterm"/> <a id="idx10326" class="indexterm"/> <a id="idx10334" class="indexterm"/>For a method to qualify as an overridden method in a
subclass, it must have exactly the same number and types of arguments.
It must have the same “inputs,” as it were. As we saw in the previous
section, overriding methods may refine their “output” to some extent.
Namely, they can narrow their <code class="literal">throws</code> clause by declaring that they throw
subtypes of the original method’s exception types. What about the main
“output” of a method? Its return value? Can we change the return type
of a method by overriding it? The answer is that Java gives us
covariant return types on methods just as it does for exception
types.</p><p>What this means is that when you override a method, you may
change the return type to a subtype of the original method’s return
type. For example, if our <code class="literal">Animal</code>
class has a factory method called <code class="literal">create()</code> that produces an instance of
<code class="literal">Animal</code>, our <code class="literal">Mammal</code> class could refine the return type to
<code class="literal">Mammal</code>:</p><a id="I_6_tt300"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Animal</code> <code class="o">{</code>
<code class="n">Animal</code> <code class="nf">create</code><code class="o">()</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">Mammal</code> <code class="kd">extends</code> <code class="n">Animal</code> <code class="o">{</code>
<code class="n">Mammal</code> <code class="nf">create</code><code class="o">()</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="o">}</code></pre><p>As we’ll see later, this coding technique is very helpful
because it eliminates some runtime casting of objects.<a id="I_indexterm6_id696024" class="indexterm"/><a id="I_indexterm6_id696031" class="indexterm"/><a id="I_indexterm6_id696038" class="indexterm"/><a id="I_indexterm6_id696045" class="indexterm"/><a id="I_indexterm6_id696052" class="indexterm"/></p></div></div><div class="sect2" title="Special References: this and super"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-1.3"/>Special References: this and super</h2></div></div></div><p><a id="idx10321" class="indexterm"/> <a id="idx10323" class="indexterm"/> <a id="idx10336" class="indexterm"/> <a id="idx10339" class="indexterm"/>The special references <code class="literal">this</code> and <code class="literal">super</code> allow you to refer to the members of the
current object instance or to members of the superclass, respectively.
We have seen <code class="literal">this</code> used elsewhere to
pass a reference to the current object and to refer to shadowed instance
variables. The reference <a id="I_indexterm6_id696138" class="indexterm"/><code class="literal">super</code> does the same for
the parents of a class. You can use it to refer to members of a
superclass that have been shadowed or overridden. Being able to invoke
the original method of the superclass allows us to use it as part of our
new method, delegating to its behavior before or after we perform
additional work:</p><a id="I_6_tt301"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Animal</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">eat</code><code class="o">(</code> <code class="n">Food</code> <code class="n">f</code> <code class="o">)</code> <code class="kd">throws</code> <code class="n">InedibleException</code> <code class="o">{</code>
<code class="c1">// consume food</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">Herbivore</code> <code class="kd">extends</code> <code class="n">Animal</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">eat</code><code class="o">(</code> <code class="n">Food</code> <code class="n">f</code> <code class="o">)</code> <code class="kd">throws</code> <code class="n">MeatInedibleException</code> <code class="o">{</code>
<code class="c1">// check if edible</code>
<code class="o">...</code>
<code class="k">try</code> <code class="o">{</code>
<code class="kd">super</code><code class="o">.</code><code class="na">eat</code><code class="o">(</code> <code class="n">f</code> <code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InedibleException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>In this example, our <code class="literal">Herbivore</code>
class overrides the <code class="literal">Animal eat()</code>
method to first do some checking on the <code class="literal">food</code> object. After doing its job, it uses
<code class="literal">super.eat()</code> to call the (otherwise
overridden and inaccessible) implementation of <code class="literal">eat()</code> in its superclass.</p><p><code class="literal">super</code> prompts a search for the
method or variable to begin in the scope of the immediate superclass
rather than the current class. The inherited method or variable found
may reside in the immediate superclass or one further up the tree. The
usage of the <code class="literal">super</code> reference when
applied to overridden methods of a superclass is special; it tells the
method resolution system to stop the dynamic method search at the
superclass instead of at the most derived class (as it otherwise does).
Without <code class="literal">super</code>, there would be no way
to access overridden methods.</p></div><div class="sect2" title="Casting"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-1.4"/>Casting</h2></div></div></div><p><a id="idx10271" class="indexterm"/> <a id="idx10318" class="indexterm"/> <a id="idx10329" class="indexterm"/>A <span class="emphasis"><em>cast</em></span> explicitly tells the compiler
to change the apparent type of an object reference. The main use for
casts is when an object is temporarily assigned to a more general type.
For example, if a <code class="literal">String</code> were
assigned to a variable of type <code class="literal">Object</code>, to use it as a <code class="literal">String</code> again, we’d have to perform a cast to
get it back. The compiler recognizes only the declared types of
variables and doesn’t know that we actually placed a <code class="literal">String</code> into it. In Java, casts are checked
both at compile time and at runtime to make sure they are legal. At
compile time the Java compiler will stop you from trying to perform a
cast that cannot possibly work (such as turning a <code class="literal">Date</code> directly into a <code class="literal">String</code>). And at runtime, Java will check that
casts that are plausible (such as our <code class="literal">Object</code> to <code class="literal">String</code>) are actually correct for the real
objects involved.</p><p>Attempting to cast an object to an incompatible type at runtime
results in a <a id="I_indexterm6_id696318" class="indexterm"/><code class="literal">Class</code><code class="literal">Cast</code><code class="literal">Exception</code>. Only casts between objects in
the same inheritance hierarchy (and, as we’ll see later, to appropriate
interfaces) are legal in Java and pass the scrutiny of the compiler and
the runtime system. Casts in Java affect only the treatment of
references; they never change the form of the actual object. This is an
important rule to keep in mind. You never change the object pointed to
by a reference by casting it; you change only the compiler’s (or runtime
system’s) notion of it.</p><p>A cast can be used to <a id="I_indexterm6_id696352" class="indexterm"/><span class="emphasis"><em>narrow</em></span> or <a id="I_indexterm6_id696360" class="indexterm"/><span class="emphasis"><em>downcast</em></span> the type of a reference—to
make it more specific. Often, we’ll do this when we have to retrieve an
object from a more general type of collection or when it has been
previously used as a less derived type. (The prototypical example is
using an object in a collection, as we’ll see in <a class="xref" href="ch11.html" title="Chapter 11. Core Utilities">Chapter 11</a>.) Continuing with our <code class="literal">Cat</code> example:</p><a id="I_6_tt302"/><pre class="programlisting"> <code class="n">Animal</code> <code class="n">creature</code><code class="o">;</code>
<code class="n">Cat</code> <code class="n">simon</code><code class="o">;</code>
<code class="c1">// ...</code>
<code class="n">creature</code> <code class="o">=</code> <code class="n">simon</code><code class="o"