📄 tij0050.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0049.html">Prev</a> | <a href="tij0051.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Method
overloading
<P><A NAME="Index270"></A><A NAME="Index271"></A></H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
of the important features in any programming language is the use of names. When
you create an object, you give a name to a region of storage. A method is a
name for an action. By using names to describe your system, you create a
program that is easier for people to understand and change. It’s a lot
like writing prose – the goal is to communicate with your readers.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
refer to all objects and methods by using names. Well-chosen names make it
easier for you and others to understand your code.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
problem arises when mapping the concept of nuance in human language onto a
programming language. Often, the same word expresses a number of different
meanings – it’s
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>overloaded</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is useful, especially when it comes to trivial differences. You say
“wash the shirt,” “wash the car,” and “wash the
dog.” It would be silly to be forced to say, “shirtWash the
shirt,” “carWash the car,” and “dogWash the dog”
just so the listener doesn’t need to make any distinction about the
action performed. Most human languages are redundant, so even if you miss a few
words, you can still determine the meaning. We don’t need unique
identifiers – we can deduce meaning from context.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Most
programming languages (C in particular) require you to have a unique identifier
for each function. So you could not have one function called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for printing integers and another called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for printing floats – each function requires a unique name.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
Java, another factor forces the overloading of method names: the constructor<A NAME="Index272"></A><A NAME="Index273"></A>.
Because the constructor’s name is predetermined by the name of the class,
there can be only one constructor name. But what if you want to create an
object in more than one way? For example, suppose you build a class that can
initialize itself in a standard way and by reading information from a file. You
need two constructors, one that takes no arguments (the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>default</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor), and one that takes a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as an argument, which is the name of the file from which to initialize the
object. Both are constructors, so they must have the same name – the name
of the class. Thus
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>method
overloading
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is essential to allow the same method name to be used with different argument
types. And although method overloading is a must for constructors, it’s a
general convenience and can be used with any method.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here’s
an example that shows both overloaded constructors and overloaded ordinary
methods:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Overloading.java</font>
<font color="#009900">// Demonstration of both constructor</font>
<font color="#009900">// and ordinary method overloading.</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Tree {
<font color="#0000ff">int</font> height;
Tree() {
prt("Planting a seedling");
height = 0;
}
Tree(<font color="#0000ff">int</font> i) {
prt("Creating <font color="#0000ff">new</font> Tree that is "
+ i + " feet tall");
height = i;
}
<font color="#0000ff">void</font> info() {
prt("Tree is " + height
+ " feet tall");
}
<font color="#0000ff">void</font> info(String s) {
prt(s + ": Tree is "
+ height + " feet tall");
}
<font color="#0000ff">static</font> <font color="#0000ff">void</font> prt(String s) {
System.out.println(s);
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Overloading {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 5; i++) {
Tree t = <font color="#0000ff">new</font> Tree(i);
t.info();
t.info("overloaded method");
}
<font color="#009900">// Overloaded constructor:</font>
<font color="#0000ff">new</font> Tree();
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Tree</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object can be created either as a seedling, with no argument, or as a plant
grown in a nursery, with an existing height. To support this, there are two
constructors, one that takes no arguments (we call constructors that take no
arguments <A NAME="Index274"></A><A NAME="Index275"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>default
constructors
</I></FONT><A NAME="fnB17" HREF="#fn17">[17]</A><A NAME="Index276"></A><A NAME="Index277"></A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
and one that takes the existing height.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might also want to call the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>info( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method in more than one way. For example, with a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
argument if you have an extra message you want printed, and without if you have
nothing more to say. It would seem strange to give two separate names to what
is obviously the same concept. Fortunately, method overloading allows you to
use the same name for both.
</FONT><a name="_Toc375545277"></a><a name="_Toc408018478"></a><P></DIV>
<A NAME="Heading140"></A><H3 ALIGN=LEFT>
Distinguishing
overloaded methods
<P><A NAME="Index278"></A><A NAME="Index279"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
the methods have the same name, how can Java know which method you mean?
There’s a simple rule: Each overloaded method must take a unique list of
argument types.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you think about this for a second, it makes sense: how else could a programmer
tell the difference between two methods that have the same name, other than by
the types of their arguments?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Even
differences in the ordering of arguments is sufficient to distinguish two
methods: (Although you don’t normally want to take this approach, as it
produces difficult-to-maintain code.)
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: OverloadingOrder.java</font>
<font color="#009900">// Overloading based on the order of</font>
<font color="#009900">// the arguments.</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> OverloadingOrder {
<font color="#0000ff">static</font> <font color="#0000ff">void</font> print(String s, <font color="#0000ff">int</font> i) {
System.out.println(
"String: " + s +
", <font color="#0000ff">int</font>: " + i);
}
<font color="#0000ff">static</font> <font color="#0000ff">void</font> print(<font color="#0000ff">int</font> i, String s) {
System.out.println(
"<font color="#0000ff">int</font>: " + i +
", String: " + s);
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
print("String first", 11);
print(99, "Int first");
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
two
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods have identical arguments, but the order is different, and that’s
what makes them distinct.
</FONT><a name="_Toc408018479"></a><a name="_Toc312373866"></a><a name="_Toc375545278"></a><P></DIV>
<A NAME="Heading141"></A><H3 ALIGN=LEFT>
Overloading
with primitives
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Primitives
can be automatically promoted from a smaller type to a larger one and this can
be slightly confusing in combination with overloading. The following example
demonstrates what happens when a primitive is handed to an overloaded method:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: PrimitiveOverloading.java</font>
<font color="#009900">// Promotion of primitives and overloading</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> PrimitiveOverloading {
<font color="#009900">// boolean can't be automatically converted</font>
<font color="#0000ff">static</font> <font color="#0000ff">void</font> prt(String s) {
System.out.println(s);
}
<font color="#0000ff">void</font> f1(<font color="#0000ff">char</font> x) { prt("f1(<font color="#0000ff">char</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">byte</font> x) { prt("f1(<font color="#0000ff">byte</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">short</font> x) { prt("f1(<font color="#0000ff">short</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">int</font> x) { prt("f1(<font color="#0000ff">int</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">long</font> x) { prt("f1(<font color="#0000ff">long</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">float</font> x) { prt("f1(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f1(<font color="#0000ff">double</font> x) { prt("f1(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">byte</font> x) { prt("f2(<font color="#0000ff">byte</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">short</font> x) { prt("f2(<font color="#0000ff">short</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">int</font> x) { prt("f2(<font color="#0000ff">int</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">long</font> x) { prt("f2(<font color="#0000ff">long</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">float</font> x) { prt("f2(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f2(<font color="#0000ff">double</font> x) { prt("f2(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f3(<font color="#0000ff">short</font> x) { prt("f3(<font color="#0000ff">short</font>)"); }
<font color="#0000ff">void</font> f3(<font color="#0000ff">int</font> x) { prt("f3(<font color="#0000ff">int</font>)"); }
<font color="#0000ff">void</font> f3(<font color="#0000ff">long</font> x) { prt("f3(<font color="#0000ff">long</font>)"); }
<font color="#0000ff">void</font> f3(<font color="#0000ff">float</font> x) { prt("f3(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f3(<font color="#0000ff">double</font> x) { prt("f3(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f4(<font color="#0000ff">int</font> x) { prt("f4(<font color="#0000ff">int</font>)"); }
<font color="#0000ff">void</font> f4(<font color="#0000ff">long</font> x) { prt("f4(<font color="#0000ff">long</font>)"); }
<font color="#0000ff">void</font> f4(<font color="#0000ff">float</font> x) { prt("f4(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f4(<font color="#0000ff">double</font> x) { prt("f4(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f5(<font color="#0000ff">long</font> x) { prt("f5(<font color="#0000ff">long</font>)"); }
<font color="#0000ff">void</font> f5(<font color="#0000ff">float</font> x) { prt("f5(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f5(<font color="#0000ff">double</font> x) { prt("f5(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f6(<font color="#0000ff">float</font> x) { prt("f6(<font color="#0000ff">float</font>)"); }
<font color="#0000ff">void</font> f6(<font color="#0000ff">double</font> x) { prt("f6(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> f7(<font color="#0000ff">double</font> x) { prt("f7(<font color="#0000ff">double</font>)"); }
<font color="#0000ff">void</font> testConstVal() {
prt("Testing with 5");
f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);
}
<font color="#0000ff">void</font> testChar() {
<font color="#0000ff">char</font> x = 'x';
prt("<font color="#0000ff">char</font> argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
<font color="#0000ff">void</font> testByte() {
<font color="#0000ff">byte</font> x = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -