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

📄 chap12.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) + 
        <font color=#004488>" quantity: "</font> + cnt.i);
    }
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here, the <B>typenames</B> array has been
removed in favor of getting the type name strings from the <B>Class</B> object.
Notice that the system can distinguish between classes and interfaces.

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

<backtalk:display ID=TIJ3_CHAPTER12_I25>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can also see that the creation of
<B>petTypes</B> does not need to be surrounded by a <B>try</B> block since
it&#8217;s evaluated at compile-time and thus won&#8217;t throw any exceptions,
unlike <B>Class.forName(&#160;)</B>.

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

<backtalk:display ID=TIJ3_CHAPTER12_I26>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the <B>Pet</B> objects are
dynamically created, you can see that the random number is restricted so it is
between one and <B>petTypes.length</B> and does not include zero. That&#8217;s
because zero refers to <B>Pet.class</B>, and presumably a generic <B>Pet</B>
object is not interesting. However, since <B>Pet.class</B> is part of
<B>petTypes</B> the result is that all of the pets get counted.

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

<backtalk:display ID=TIJ3_CHAPTER12_I27>
</FONT><BR></P></DIV>
<A NAME="Heading407"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
A dynamic instanceof<BR><A NAME="Index1500"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>Class</B>
<A NAME="Index1501"></A><A NAME="Index1502"></A><A NAME="Index1503"></A><B>isInstance</B>
method provides a way to dynamically call the <B>instanceof</B> operator. Thus,
all those tedious <B>instanceof</B> statements can be removed in the
<B>PetCount</B> example:</FONT><BR></P></DIV>

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

<font color=#0000ff>public</font> <font color=#0000ff>class</font> PetCount3 {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) 
  <font color=#0000ff>throws</font> Exception {
    ArrayList pets = <font color=#0000ff>new</font> ArrayList();
    Class[] petTypes = {
      Pet.<font color=#0000ff>class</font>,
      Dog.<font color=#0000ff>class</font>,
      Pug.<font color=#0000ff>class</font>,
      Cat.<font color=#0000ff>class</font>,
      Rodent.<font color=#0000ff>class</font>,
      Gerbil.<font color=#0000ff>class</font>,
      Hamster.<font color=#0000ff>class</font>,
    };
    <font color=#0000ff>try</font> {
      <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 15; i++) {
        <font color=#009900>// Offset by one to eliminate Pet.class:</font>
        <font color=#0000ff>int</font> rnd = 1 + (<font color=#0000ff>int</font>)(
          Math.random() * (petTypes.length - 1));
        pets.add(
          petTypes[rnd].newInstance());
      }
    } <font color=#0000ff>catch</font>(InstantiationException e) {
      System.err.println(<font color=#004488>"Cannot instantiate"</font>);
      <font color=#0000ff>throw</font> e;
    } <font color=#0000ff>catch</font>(IllegalAccessException e) {
      System.err.println(<font color=#004488>"Cannot access"</font>);
      <font color=#0000ff>throw</font> e;
    }
    HashMap h = <font color=#0000ff>new</font> HashMap();
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; petTypes.length; i++)
      h.put(petTypes[i].toString(),
        <font color=#0000ff>new</font> Counter());
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; pets.size(); i++) {
      Object o = pets.get(i);
      <font color=#009900>// Using isInstance to eliminate individual</font>
      <font color=#009900>// instanceof expressions:</font>
      <font color=#0000ff>for</font> (<font color=#0000ff>int</font> j = 0; j &lt; petTypes.length; ++j)
        <font color=#0000ff>if</font> (petTypes[j].isInstance(o)) {
          String key = petTypes[j].toString();
          ((Counter)h.get(key)).i++;
        }
    }
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; pets.size(); i++)
      System.out.println(pets.get(i).getClass());
    Iterator keys = h.keySet().iterator();
    <font color=#0000ff>while</font>(keys.hasNext()) {
      String nm = (String)keys.next();
      Counter cnt = (Counter)h.get(nm);
      System.out.println(
        nm.substring(nm.lastIndexOf('.') + 1) + 
        <font color=#004488>" quantity: "</font> + cnt.i);
    }
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that the
<B>isInstance(&#160;)</B> method has eliminated the need for the
<B>instanceof</B> expressions. In addition, this means that you can add new
types of pets simply by changing the <B>petTypes</B> array; the rest of the
program does not need modification (as it did when using the <B>instanceof</B>
expressions). 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I27' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER12_I28>
</FONT><BR></P></DIV>
<A NAME="Heading408"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
instanceof vs. Class equivalence<BR><A NAME="Index1504"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When querying for type information,
there&#8217;s an important difference between either form of <B>instanceof</B>
(that is, <B>instanceof</B> or <B>isInstance(&#160;)</B>, which produce
equivalent results) and the direct comparison of the <B>Class</B> objects.
Here&#8217;s an example that demonstrates the difference:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:FamilyVsExactType.java</font>
<font color=#009900>// The difference between instanceof and class</font>

<font color=#0000ff>class</font> Base {}
<font color=#0000ff>class</font> Derived <font color=#0000ff>extends</font> Base {}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> FamilyVsExactType {
  <font color=#0000ff>static</font> <font color=#0000ff>void</font> test(Object x) {
    System.out.println(<font color=#004488>"Testing x of type "</font> +
      x.getClass());
    System.out.println(<font color=#004488>"x instanceof Base "</font> +
      (x <font color=#0000ff>instanceof</font> Base));
    System.out.println(<font color=#004488>"x instanceof Derived "</font> +
      (x <font color=#0000ff>instanceof</font> Derived));
    System.out.println(<font color=#004488>"Base.isInstance(x) "</font> +
      Base.<font color=#0000ff>class</font>.isInstance(x));
    System.out.println(<font color=#004488>"Derived.isInstance(x) "</font> +
      Derived.<font color=#0000ff>class</font>.isInstance(x));
    System.out.println(
      <font color=#004488>"x.getClass() == Base.class "</font> +
      (x.getClass() == Base.<font color=#0000ff>class</font>));
    System.out.println(
      <font color=#004488>"x.getClass() == Derived.class "</font> +
      (x.getClass() == Derived.<font color=#0000ff>class</font>));
    System.out.println(
      <font color=#004488>"x.getClass().equals(Base.class)) "</font> +
      (x.getClass().equals(Base.<font color=#0000ff>class</font>)));
    System.out.println(
      <font color=#004488>"x.getClass().equals(Derived.class)) "</font> +
      (x.getClass().equals(Derived.<font color=#0000ff>class</font>)));
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    test(<font color=#0000ff>new</font> Base());
    test(<font color=#0000ff>new</font> Derived());
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>test(&#160;)</B> method performs
type checking with its argument using both forms of <B>instanceof</B>. It then
gets the <B>Class</B> reference and uses <B>==</B> and <B>equals(&#160;) </B>to
test for equality of the <B>Class</B> objects. Here is the
output:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Testing x of type <font color=#0000ff>class</font> Base
x <font color=#0000ff>instanceof</font> Base <font color=#0000ff>true</font>
x <font color=#0000ff>instanceof</font> Derived <font color=#0000ff>false</font>
Base.isInstance(x) <font color=#0000ff>true</font>
Derived.isInstance(x) <font color=#0000ff>false</font>
x.getClass() == Base.<font color=#0000ff>class</font> <font color=#0000ff>true</font>
x.getClass() == Derived.<font color=#0000ff>class</font> <font color=#0000ff>false</font>
x.getClass().equals(Base.<font color=#0000ff>class</font>)) <font color=#0000ff>true</font>
x.getClass().equals(Derived.<font color=#0000ff>class</font>)) <font color=#0000ff>false</font>
Testing x of type <font color=#0000ff>class</font> Derived
x <font color=#0000ff>instanceof</font> Base <font color=#0000ff>true</font>
x <font color=#0000ff>instanceof</font> Derived <font color=#0000ff>true</font>
Base.isInstance(x) <font color=#0000ff>true</font>
Derived.isInstance(x) <font color=#0000ff>true</font>
x.getClass() == Base.<font color=#0000ff>class</font> <font color=#0000ff>false</font>
x.getClass() == Derived.<font color=#0000ff>class</font> <font color=#0000ff>true</font>
x.getClass().equals(Base.<font color=#0000ff>class</font>)) <font color=#0000ff>false</font>
x.getClass().equals(Derived.<font color=#0000ff>class</font>)) <font color=#0000ff>true</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Reassuringly, <B>instanceof </B>and
<B>isInstance(&#160;)</B> produce exactly the same results, as do
<B>equals(&#160;)</B> and <B>==</B>. But the tests themselves draw different
conclusions. In keeping with the concept of type, <B>instanceof</B> says
&#8220;are you this class, or a class derived from this class?&#8221; On the
other hand, if you compare the actual <B>Class</B> objects using <B>==</B>,
there is no concern with inheritance&#8212;it&#8217;s either the exact type or
it isn&#8217;t.

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

<backtalk:display ID=TIJ3_CHAPTER12_I29>
</FONT><A NAME="_Toc305593313"></A><A NAME="_Toc305628785"></A><A NAME="_Toc312374146"></A><A NAME="_Toc375545409"></A><A NAME="_Toc375545407"></A><A NAME="_Toc481064776"></A><BR></P></DIV>
<A NAME="Heading409"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
RTTI syntax</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Java performs its
<A NAME="Index1505"></A><A NAME="Index1506"></A>RTTI using the <B>Class</B>
object, even if you&#8217;re doing something like a cast. The class <B>Class</B>
also has a number of other ways you can use RTTI.

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

<backtalk:display ID=TIJ3_CHAPTER12_I30>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">First, you must get a reference to the
appropriate <B>Class</B> object. One way to do this, as shown in the previous
example, is to use a string and the <B>Class.forName(&#160;)</B> method. This is
convenient because you don&#8217;t need an object of that type in order to get
the <B>Class</B> reference. However, if you do already have an object of the
type you&#8217;re interested in, you can fetch the <B>Class</B> reference by
calling a method that&#8217;s part of the <B>Object</B> root class:<B>
<A NAME="Index1507"></A><A NAME="Index1508"></A>getClass(&#160;)</B>. This
returns the <B>Class</B> reference representing the actual type of the object.
<B>Class</B> has many interesting methods, demonstrated in the following
example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c12:ToyTest.java</font>
<font color=#009900>// Testing class Class.</font>

<font color=#0000ff>interface</font> HasBatteries {}
<font color=#0000ff>interface</font> Waterproof {}
<font color=#0000ff>interface</font> ShootsThings {}
<font color=#0000ff>class</font> Toy {
  <font color=#009900>// Comment out the following default</font>
  <font color=#009900>// constructor to see </font>
  <font color=#009900>// NoSuchMethodError from (*1*)</font>
  Toy() {} 
  Toy(<font color=#0000ff>int</font> i) {} 
}

<font color=#0000ff>class</font> FancyToy <font color=#0000ff>extends</font> Toy 
    <font color=#0000ff>implements</font> HasBatteries, 
      Waterproof, ShootsThings {
  FancyToy() { <font color=#0000ff>super</font>(1); }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> ToyTest {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) 
  <font color=#0000ff>throws</font> Exception {

⌨️ 快捷键说明

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