📄 chapter11.html
字号:
<font color=#0000ff>class</font> Cat <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Rodent <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Gerbil <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Hamster <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Counter { <font color=#0000ff>int</font> i; }
<font color=#0000ff>public</font> <font color=#0000ff>class</font> PetCount {
<font color=#0000ff>static</font> String[] typenames = {
<font color=#004488>"Pet"</font>, <font color=#004488>"Dog"</font>, <font color=#004488>"Pug"</font>, <font color=#004488>"Cat"</font>,
<font color=#004488>"Rodent"</font>, <font color=#004488>"Gerbil"</font>, <font color=#004488>"Hamster"</font>,
};
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Vector pets = <font color=#0000ff>new</font> Vector();
<font color=#0000ff>try</font> {
Class[] petTypes = {
Class.forName(<font color=#004488>"c11.petcount.Dog"</font>),
Class.forName(<font color=#004488>"c11.petcount.Pug"</font>),
Class.forName(<font color=#004488>"c11.petcount.Cat"</font>),
Class.forName(<font color=#004488>"c11.petcount.Rodent"</font>),
Class.forName(<font color=#004488>"c11.petcount.Gerbil"</font>),
Class.forName(<font color=#004488>"c11.petcount.Hamster"</font>),
};
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 15; i++)
pets.addElement(
petTypes[
(<font color=#0000ff>int</font>)(Math.random()*petTypes.length)]
.newInstance());
} <font color=#0000ff>catch</font>(InstantiationException e) {}
<font color=#0000ff>catch</font>(IllegalAccessException e) {}
<font color=#0000ff>catch</font>(ClassNotFoundException e) {}
Hashtable h = <font color=#0000ff>new</font> Hashtable();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < typenames.length; i++)
h.put(typenames[i], <font color=#0000ff>new</font> Counter());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.size(); i++) {
Object o = pets.elementAt(i);
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pet)
((Counter)h.get(<font color=#004488>"Pet"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Dog)
((Counter)h.get(<font color=#004488>"Dog"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pug)
((Counter)h.get(<font color=#004488>"Pug"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Cat)
((Counter)h.get(<font color=#004488>"Cat"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Rodent)
((Counter)h.get(<font color=#004488>"Rodent"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Gerbil)
((Counter)h.get(<font color=#004488>"Gerbil"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Hamster)
((Counter)h.get(<font color=#004488>"Hamster"</font>)).i++;
}
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.size(); i++)
System.out.println(
pets.elementAt(i).getClass().toString());
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < typenames.length; i++)
System.out.println(
typenames[i] + <font color=#004488>" quantity: "</font> +
((Counter)h.get(typenames[i])).i);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc305593310"></A><A NAME="_Toc305628782"></A><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There’s a rather narrow
restriction on <B>instanceof </B>in Java 1.0<A NAME="Index1386"></A>: You can
compare it to a named type only, and not to a <B>Class</B> object. In the
example above you might feel that it’s tedious to write out all of those
<B>instanceof</B> expressions, and you’re right. But in Java 1.0 there is
no way to cleverly automate it by creating a <B>Vector</B> of <B>Class</B>
objects and comparing it to those instead. This isn’t as great a
restriction as you might think, because you’ll eventually understand that
your design is probably flawed if you end up writing a lot of <B>instanceof</B>
expressions.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course this example is contrived
– you’d probably put a <B>static</B> data member in each type and
increment it in the constructor to keep track of the counts. You would do
something like that <I>if</I> you had control of the source code for the class
and could change it. Since this is not always the case, RTTI can come in
handy.</FONT><BR></P></DIV>
<A NAME="Heading356"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Using class literals</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It’s interesting to see how
the <B>PetCount.java</B> example can be rewritten using Java
1.1<A NAME="Index1387"></A> class
literals<A NAME="Index1388"></A><A NAME="Index1389"></A>. The result is cleaner
in many ways:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: PetCount2.java</font>
<font color=#009900>// Using Java 1.1 class literals</font>
<font color=#0000ff>package</font> c11.petcount2;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>class</font> Pet {}
<font color=#0000ff>class</font> Dog <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Pug <font color=#0000ff>extends</font> Dog {}
<font color=#0000ff>class</font> Cat <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Rodent <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Gerbil <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Hamster <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Counter { <font color=#0000ff>int</font> i; }
<font color=#0000ff>public</font> <font color=#0000ff>class</font> PetCount2 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Vector pets = <font color=#0000ff>new</font> Vector();
Class[] petTypes = {
<font color=#009900>// Class literals work in Java 1.1+ only:</font>
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 < 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.addElement(
petTypes[rnd].newInstance());
}
} <font color=#0000ff>catch</font>(InstantiationException e) {}
<font color=#0000ff>catch</font>(IllegalAccessException e) {}
Hashtable h = <font color=#0000ff>new</font> Hashtable();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 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 < pets.size(); i++) {
Object o = pets.elementAt(i);
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pet)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Pet"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Dog)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Dog"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Pug)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Pug"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Cat)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Cat"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Rodent)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Rodent"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Gerbil)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Gerbil"</font>)).i++;
<font color=#0000ff>if</font>(o <font color=#0000ff>instanceof</font> Hamster)
((Counter)h.get(
<font color=#004488>"class c11.petcount2.Hamster"</font>)).i++;
}
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < pets.size(); i++)
System.out.println(
pets.elementAt(i).getClass().toString());
Enumeration keys = h.keys();
<font color=#0000ff>while</font>(keys.hasMoreElements()) {
String nm = (String)keys.nextElement();
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 the extra work for this: the class name is not, for example,
<B>Gerbil,</B> but instead <B>c11.petcount2.Gerbil</B> since the package name is
included. Notice also that the system can distinguish between classes and
interfaces.</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’s evaluated at compile time and thus won’t throw any exceptions,
unlike <B>Class.forName( )</B>.</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 1 and <B>petTypes.length</B> and does not include zero. That’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.</FONT><BR></P></DIV>
<A NAME="Heading357"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
A dynamic instanceof<BR><A NAME="Index1390"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Java 1.1<A NAME="Index1391"></A>
has added the
<A NAME="Index1392"></A><A NAME="Index1393"></A><A NAME="Index1394"></A><B>isInstance</B>
method to the class <B>Class</B>. This allows you to dynamically call the
<B>instanceof</B> operator, which you could do only statically in Java
1.0<A NAME="Index1395"></A> (as previously shown). 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>//: PetCount3.java</font>
<font color=#009900>// Using Java 1.1 isInstance()</font>
<font color=#0000ff>package</font> c11.petcount3;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>class</font> Pet {}
<font color=#0000ff>class</font> Dog <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Pug <font color=#0000ff>extends</font> Dog {}
<font color=#0000ff>class</font> Cat <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Rodent <font color=#0000ff>extends</font> Pet {}
<font color=#0000ff>class</font> Gerbil <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Hamster <font color=#0000ff>extends</font> Rodent {}
<font color=#0000ff>class</font> Counter { <font color=#0000ff>int</font> i; }
<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) {
Vector pets = <font color=#0000ff>new</font> Vector();
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 < 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.addElement(
petTypes[rnd].newInstance());
}
} <font color=#0000ff>catch</font>(InstantiationException e) {}
<font color=#0000ff>catch</font>(IllegalAccessException e) {}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -