📄 chap12.htm
字号:
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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I24'
target="_blank">Add Comment</a> ]
<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’s evaluated at compile-time and thus won’t throw any exceptions,
unlike <B>Class.forName( )</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I25'
target="_blank">Add Comment</a> ]
<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’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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I26'
target="_blank">Add Comment</a> ]
<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 < 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 < 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.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 < 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 < 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( )</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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I27'
target="_blank">Add Comment</a> ]
<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’s an important difference between either form of <B>instanceof</B>
(that is, <B>instanceof</B> or <B>isInstance( )</B>, which produce
equivalent results) and the direct comparison of the <B>Class</B> objects.
Here’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( )</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( ) </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( )</B> produce exactly the same results, as do
<B>equals( )</B> and <B>==</B>. But the tests themselves draw different
conclusions. In keeping with the concept of type, <B>instanceof</B> says
“are you this class, or a class derived from this class?” On the
other hand, if you compare the actual <B>Class</B> objects using <B>==</B>,
there is no concern with inheritance—it’s either the exact type or
it isn’t.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I28'
target="_blank">Add Comment</a> ]
<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’re doing something like a cast. The class <B>Class</B>
also has a number of other ways you can use RTTI.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER12_I29'
target="_blank">Add Comment</a> ]
<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( )</B> method. This is
convenient because you don’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’re interested in, you can fetch the <B>Class</B> reference by
calling a method that’s part of the <B>Object</B> root class:<B>
<A NAME="Index1507"></A><A NAME="Index1508"></A>getClass( )</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 + -