⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap12.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIJ2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:05/21/2001
Translation Time:10:39:21
Translation Platform:Win32
Number of Output files:23
This File:Chap12.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>12: Run-time Type Identification</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana" size = "-1">
    [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevHist.htm">Revision History</a> ]
    [ <a href="http://www.mindview.net/Books/TIJ/">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana">
  Thinking in Java, 2nd edition, Revision 12</FONT></H2>
  <H3><FONT FACE="Verdana">&copy;2000 by Bruce Eckel</FONT></H3>
  
    <FONT FACE="Verdana" size = "-1">
     [ <a href="Chap11.htm">Previous Chapter</a> ] 
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
    [ <a href="DocIdx.htm">Index</a> ]
     [ <a href="Chap13.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="Chapter_11"></A><A NAME="Chapter_12"></A><A NAME="_Toc375545404"></A><A NAME="_Toc477690732"></A><A NAME="_Toc481064772"></A><A NAME="Heading401"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
12: Run-time Type Identification</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4><backtalk:display ID=TIJ3_CHAPTER12_I0>
The idea
of run-time type identification (RTTI) seems fairly simple at first: it lets you
find the exact type of an object when you only have a reference to the base
type. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">However, the <I>need</I> for RTTI
uncovers a whole plethora of interesting (and often perplexing) OO design
issues, and raises fundamental questions of how you should structure your
programs.  
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I0' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I1>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This chapter looks at the ways that Java
allows you to discover information about objects and classes at run-time. This
takes two forms: &#8220;traditional&#8221; RTTI, which assumes that you have all
the types available at compile-time and run-time, and the
&#8220;reflection&#8221; mechanism, which allows you to discover class
information solely at run-time. The &#8220;traditional&#8221; RTTI will be
covered first, followed by a discussion of reflection.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I1' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I2>
</FONT><A NAME="_Toc375545405"></A><A NAME="_Toc481064773"></A><BR></P></DIV>
<A NAME="Heading402"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
The need for RTTI</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Consider the now familiar example of a
class hierarchy that uses polymorphism. The generic type is the base class
<B>Shape<A NAME="Index1466"></A><A NAME="Index1467"></A></B>, and the specific
derived types are <B>Circle</B>, <B>Square</B>, and
<B>Triangle</B>:</FONT><BR></P></DIV>
<DIV ALIGN="CENTER"><FONT FACE="Georgia"><IMG SRC="TIJ227.gif"></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is a typical class hierarchy
diagram, with the base class at the top and the derived classes growing
downward. The normal goal in object-oriented
programming<A NAME="Index1468"></A><A NAME="Index1469"></A> is for the bulk of
your code to manipulate references to the base type (<B>Shape</B>, in this
case), so if you decide to extend the program by adding a new class
(<B>Rhomboid</B>, derived from <B>Shape</B>, for example), the bulk of the code
is not affected. In this example, the dynamically bound method in the
<B>Shape</B> interface is <B>draw(&#160;)</B>, so the intent is for the client
programmer to call <B>draw(&#160;)</B> through a generic <B>Shape</B> reference.
<B>draw(&#160;)</B> is overridden in all of the derived classes, and because it
is a dynamically bound method, the proper behavior will occur even though it is
called through a generic <B>Shape</B> reference. That&#8217;s
<A NAME="Index1470"></A>polymorphism.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I2' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I3>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Thus, you generally create a specific
object (<B>Circle</B>, <B>Square</B>, or <B>Triangle</B>), upcast it to a
<B>Shape</B> (forgetting the specific type of the object), and use that
anonymous <B>Shape </B>reference in the rest of the program.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I3' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I4>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As a brief review of polymorphism and
<A NAME="Index1471"></A>upcasting, you might code the above example as
follows:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:Shapes.java</font>
<font color=#0000ff>import</font> java.util.*;

<font color=#0000ff>class</font> Shape {
  <font color=#0000ff>void</font> draw() {
    System.out.println(<font color=#0000ff>this</font> + <font color=#004488>".draw()"</font>);
  }
}

<font color=#0000ff>class</font> Circle <font color=#0000ff>extends</font> Shape {
  <font color=#0000ff>public</font> String toString() { <font color=#0000ff>return</font> <font color=#004488>"Circle"</font>; }
}

<font color=#0000ff>class</font> Square <font color=#0000ff>extends</font> Shape {
  <font color=#0000ff>public</font> String toString() { <font color=#0000ff>return</font> <font color=#004488>"Square"</font>; }
}

<font color=#0000ff>class</font> Triangle <font color=#0000ff>extends</font> Shape {
  <font color=#0000ff>public</font> String toString() { <font color=#0000ff>return</font> <font color=#004488>"Triangle"</font>; }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Shapes {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    ArrayList s = <font color=#0000ff>new</font> ArrayList();
    s.add(<font color=#0000ff>new</font> Circle());
    s.add(<font color=#0000ff>new</font> Square());
    s.add(<font color=#0000ff>new</font> Triangle());
    Iterator e = s.iterator();
    <font color=#0000ff>while</font>(e.hasNext())
      ((Shape)e.next()).draw();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The base class contains a
<B>draw(&#160;)</B> method that indirectly uses <B>toString(&#160;) </B>to print
an identifier for the class by passing <B>this</B> to
<B>System.out.println(&#160;)</B>. If that function sees an object, it
automatically calls the <B>toString(&#160;)</B> method to produce a
<B>String</B> representation.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I4' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I5>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Each of the derived classes overrides the
<B>toString(&#160;)</B> method (from <B>Object</B>) so that <B>draw(&#160;)</B>
ends up printing something different in each case. In <B>main(&#160;)</B>,
specific types of <B>Shape</B> are created and then added to a<STRIKE>n</STRIKE>
<B><STRIKE>Array</STRIKE>List</B>. This is the point at which the upcast occurs
because the <B><STRIKE>Array</STRIKE>List</B> holds only <B>Object</B>s. Since
everything in Java (with the exception of primitives) is an <B>Object</B>,
a<STRIKE>n</STRIKE> <B><STRIKE>Array</STRIKE>List</B> can also hold <B>Shape</B>
objects. But during an upcast to <B>Object</B>,<B> </B>it also loses any
specific information, including the fact that the objects are <B>Shape</B>s. To
the <B>ArrayList</B>, they are just <B>Object</B>s.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I5' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I6>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At the point you fetch an element out of
the <B><STRIKE>Array</STRIKE>List</B> with <B>next(&#160;)</B>, things get a
little busy. Since <U>the </U><B><STRIKE>Array</STRIKE>List</B> holds only
<B>Object</B>s, <B>next(&#160;)</B> naturally produces an <B>Object
reference</B>. But we know it&#8217;s really a <B>Shape</B> reference, and we
want to send <B>Shape</B> messages to that object. So a
<A NAME="Index1472"></A><A NAME="Index1473"></A>cast to <B>Shape </B>is
necessary using the traditional &#8220;<B>(Shape)</B>&#8221; cast. This is the
most basic form of RTTI, since in Java all casts are checked at run-time for
correctness. That&#8217;s exactly what RTTI means: at run-time, the type of an
object is identified. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I6' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I7>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In this case, the RTTI cast is only
partial: the <B>Object</B> is cast to a <B>Shape</B>, and not all the way to a
<B>Circle</B>, <B>Square</B>, or <B>Triangle</B>. That&#8217;s because the only
thing we <I>know</I> at this point is that the <B><STRIKE>Array</STRIKE>List</B>
is full of <B>Shape</B>s. At compile-time, this is enforced only by your own
self-imposed rules, but at run-time the cast ensures it.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I7' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I8>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now polymorphism takes over and the exact
method that&#8217;s called for the <B>Shape</B> is determined by whether the
reference is for a <B>Circle</B>, <B>Square</B>, or <B>Triangle</B>. And in
general, this is how it should be; you want the bulk of your code to know as
little as possible about <I>specific</I> types of objects, and to just deal with
the general representation of a family of objects (in this case, <B>Shape</B>).
As a result, your code will be easier to write, read, and maintain, and your
designs will be easier to implement, understand, and change. So polymorphism is
the general goal in object-oriented programming.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I8' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I9>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">But what if you have a special
programming problem that&#8217;s easiest to solve if you know the exact type of
a generic reference<A NAME="Index1474"></A><A NAME="Index1475"></A>? For
example, suppose you want to allow your users to highlight all the shapes of any
particular type by turning them purple. This way, they can find all the
triangles on the screen by highlighting them. This is what RTTI accomplishes:
you can ask a <B>Shape</B> reference the exact type that it&#8217;s referring
to.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -