📄 tij0088.html
字号:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Thus,
all you need to do to make objects of your class print out is to override the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method, as shown in the following example:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: WorksAnyway.java</font>
<font color="#009900">// In special cases, things just seem</font>
<font color="#009900">// to work correctly.</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Mouse {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> mouseNumber;
Mouse(<font color="#0000ff">int</font> i) {
mouseNumber = i;
}
<font color="#009900">// Magic method:</font>
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> "This is Mouse #" + mouseNumber;
}
<font color="#0000ff">void</font> print(String msg) {
<font color="#0000ff">if</font>(msg != <font color="#0000ff">null</font>) System.out.println(msg);
System.out.println(
"Mouse number " + mouseNumber);
}
}
<font color="#0000ff">class</font> MouseTrap {
<font color="#0000ff">static</font> <font color="#0000ff">void</font> caughtYa(Object m) {
Mouse mouse = (Mouse)m; <font color="#009900">// Cast from Object</font>
mouse.print("Caught one!");
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> WorksAnyway {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Vector mice = <font color="#0000ff">new</font> Vector();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 3; i++)
mice.addElement(<font color="#0000ff">new</font> Mouse(i));
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < mice.size(); i++) {
<font color="#009900">// No cast necessary, automatic call</font>
<font color="#009900">// to Object.toString():</font>
System.out.println(
"Free mouse: " + mice.elementAt(i));
MouseTrap.caughtYa(mice.elementAt(i));
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see the redefinition of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mouse</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In the second
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>for</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
loop in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you find the statement:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">System.out.println("Free
mouse: " + mice.elementAt(i));
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">After
the ‘
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’
sign the compiler expects to see a <A NAME="Index753"></A><A NAME="Index754"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object.
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elementAt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
produces an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so to get the desired
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the compiler implicitly calls
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Unfortunately, you can work this kind of magic only with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">;
it isn’t available for any other type.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
second approach to hiding the cast has been placed inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mousetrap</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>caughtYa( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method accepts not a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mouse</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
which it then casts to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Mouse</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is quite presumptuous, of course, since by accepting an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
anything could be passed to the method. However, if the cast is incorrect
– if you passed the wrong type – you’ll get an exception at
run-time. This is not as good as compile-time checking but it’s still
robust. Note that in the use of this method:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">MouseTrap.caughtYa(mice.elementAt(i));</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">no
cast is necessary.
</FONT><P></DIV>
<A NAME="Heading248"></A><H4 ALIGN=LEFT>
Making
a type-conscious Vector
<P><A NAME="Index755"></A><A NAME="Index756"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might not want to give up on this issue just yet. A more ironclad solution is
to create a new class using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
such that it will accept only your type and produce only your type:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: GopherVector.java</font>
<font color="#009900">// A type-conscious Vector</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Gopher {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> gopherNumber;
Gopher(<font color="#0000ff">int</font> i) {
gopherNumber = i;
}
<font color="#0000ff">void</font> print(String msg) {
<font color="#0000ff">if</font>(msg != <font color="#0000ff">null</font>) System.out.println(msg);
System.out.println(
"Gopher number " + gopherNumber);
}
}
<font color="#0000ff">class</font> GopherTrap {
<font color="#0000ff">static</font> <font color="#0000ff">void</font> caughtYa(Gopher g) {
g.print("Caught one!");
}
}
<font color="#0000ff">class</font> GopherVector {
<font color="#0000ff">private</font> Vector v = <font color="#0000ff">new</font> Vector();
<font color="#0000ff">public</font> <font color="#0000ff">void</font> addElement(Gopher m) {
v.addElement(m);
}
<font color="#0000ff">public</font> Gopher elementAt(<font color="#0000ff">int</font> index) {
<font color="#0000ff">return</font> (Gopher)v.elementAt(index);
}
<font color="#0000ff">public</font> <font color="#0000ff">int</font> size() { <font color="#0000ff">return</font> v.size(); }
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
GopherVector gophers = <font color="#0000ff">new</font> GopherVector();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 3; i++)
gophers.addElement(<font color="#0000ff">new</font> Gopher(i));
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < gophers.size(); i++)
GopherTrap.caughtYa(gophers.elementAt(i));
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is similar to the previous example, except that the new
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GopherVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class has a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">member
of type
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(inheriting from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
tends to be frustrating, for reasons you’ll see later), and methods just
like
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
However, it doesn’t accept and produce generic
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s,
only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Gopher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Because
a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GopherVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will accept only a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Gopher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
if you were to say:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">gophers.addElement(new
Pigeon());
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">you
would get an error message
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>at
compile time
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This approach, while more tedious from a coding standpoint, will tell you
immediately if you’re using a type improperly.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Note
that no cast is necessary when using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elementAt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
– it’s always a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Gopher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV>
<A NAME="Heading249"></A><H4 ALIGN=LEFT>
Parameterized
types
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
kind of problem isn’t isolated – there are numerous cases in which
you need to create new types based on other types, and in which it is useful to
have specific type information at compile-time. This is the concept of a <A NAME="Index757"></A><A NAME="Index758"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>parameterized
type
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In C++, this is directly supported by the language in <A NAME="Index759"></A><A NAME="Index760"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>templates</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
At one point, Java had reserved the keyword <A NAME="Index761"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>generic</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to someday support parameterized types, but it’s uncertain if this will
ever occur.
</FONT><a name="_Toc375545352"></a><a name="_Toc408018568"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0087.html">Prev</a> | <a href="tij0089.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -