📄 tij0120.html
字号:
<TD WIDTH=95 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Integer.TYPE</FONT></TT><P></DIV>
</TD>
</TR>
<TR VALIGN="TOP">
<TD WIDTH=89 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">long.class</FONT></TT><P></DIV>
</TD>
<TD WIDTH=95 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Long.TYPE</FONT></TT><P></DIV>
</TD>
</TR>
<TR VALIGN="TOP">
<TD WIDTH=89 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">float.class</FONT></TT><P></DIV>
</TD>
<TD WIDTH=95 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Float.TYPE</FONT></TT><P></DIV>
</TD>
</TR>
<TR VALIGN="TOP">
<TD WIDTH=89 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">double.class</FONT></TT><P></DIV>
</TD>
<TD WIDTH=95 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Double.TYPE</FONT></TT><P></DIV>
</TD>
</TR>
<TR VALIGN="TOP">
<TD WIDTH=89 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">void.class</FONT></TT><P></DIV>
</TD>
<TD WIDTH=95 COLSPAN=1 ROWSPAN=1 VALIGN=TOP>
<DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Void.TYPE</FONT></TT><P></DIV>
</TD>
</TR>
<a name="_Toc375545408"></a><a name="_Toc408018647"></a></TABLE></DIV>
<A NAME="Heading356"></A><H3 ALIGN=LEFT>
Checking
before a cast
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">So
far, you’ve seen RTTI forms including:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> The
classic cast, e.g. “
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>(Shape),</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">”
which uses RTTI to make sure the cast is correct and throws a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ClassCastException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
if you’ve performed a bad cast.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object representing the type of your object. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object can be queried for useful runtime information.
</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
C++, the classic cast “
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>(Shape)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">”
does
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>not
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">perform
RTTI. It simply tells the compiler to treat the object as the new type. In
Java, which does perform the type check, this cast is often called a
“type safe downcast<A NAME="Index1378"></A><A NAME="Index1379"></A><A NAME="Index1380"></A>.”
The reason for the term “downcast” is the historical arrangement of
the class hierarchy diagram. If casting a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is an upcast, then casting a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a downcast. However, you know a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is also a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and the compiler freely allows an upcast assignment, but you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>don’t</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
know that a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is necessarily a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so the compiler doesn’t allow you to perform a <A NAME="Index1381"></A><A NAME="Index1382"></A>downcast
assignment without using an explicit cast.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There’s
a third form of RTTI in Java. This is the <A NAME="Index1383"></A><A NAME="Index1384"></A>keyword
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that tells you if an object is an instance of a particular type. It returns a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>boolean
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">so
you use it in the form of a question, like this:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">if</font>(x <font color="#0000ff">instanceof</font> Dog)
((Dog)x).bark(); </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
above
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>if</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement checks to see if the object
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>x</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
belongs to the class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Dog</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>before</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
casting
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>x</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Dog</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
It’s important to use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
before a downcast when you don’t have other information that tells you
the type of the object; otherwise you’ll end up with a <A NAME="Index1385"></A><A NAME="Index1386"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ClassCastException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Ordinarily,
you might be hunting for one type (triangles to turn purple, for example), but
the following program shows how to tally
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>all</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of the objects using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: PetCount.java</font>
<font color="#009900">// Using instanceof</font>
<font color="#0000ff">package</font> c11.petcount;
<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> PetCount {
<font color="#0000ff">static</font> String[] typenames = {
"Pet", "Dog", "Pug", "Cat",
"Rodent", "Gerbil", "Hamster",
};
<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("c11.petcount.Dog"),
Class.forName("c11.petcount.Pug"),
Class.forName("c11.petcount.Cat"),
Class.forName("c11.petcount.Rodent"),
Class.forName("c11.petcount.Gerbil"),
Class.forName("c11.petcount.Hamster"),
};
<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("Pet")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Dog)
((Counter)h.get("Dog")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Pug)
((Counter)h.get("Pug")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Cat)
((Counter)h.get("Cat")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Rodent)
((Counter)h.get("Rodent")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Gerbil)
((Counter)h.get("Gerbil")).i++;
<font color="#0000ff">if</font>(o <font color="#0000ff">instanceof</font> Hamster)
((Counter)h.get("Hamster")).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] + " quantity: " +
((Counter)h.get(typenames[i])).i);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><a name="_Toc305593310"></a><a name="_Toc305628782"></a><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There’s
a rather narrow restriction on
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
Java 1.0<A NAME="Index1387"></A>:
You can compare it to a named type only, and not to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object. In the example above you might feel that it’s tedious to write
out all of those
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
expressions, and you’re right. But in Java 1.0 there is no way to
cleverly automate it by creating a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>instanceof</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
expressions.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Of
course this example is contrived – you’d probably put a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
data member in each type and increment it in the constructor to keep track of
the counts. You would do something like that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>if</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
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><P></DIV>
<A NAME="Heading357"></A><H4 ALIGN=LEFT>
Using
class literals
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It’s
interesting to see how the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>PetCount.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -