按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
}
// Overloaded constructor:
new Tree();
}
} ///:~
Tree 既可创建成一颗种子,不含任何自变量;亦可创建成生长在苗圃中的植物。为支持这种创建,共使用了
两个构建器,一个没有自变量(我们把没有自变量的构建器称作“默认构建器”,注释①),另一个采用现
成的高度。
①:在 Sun 公司出版的一些Java 资料中,用简陋但很说明问题的词语称呼这类构建器—— “无参数构建器”
(no…arg constructors)。但“默认构建器”这个称呼已使用了许多年,所以我选择了它。
我们也有可能希望通过多种途径调用 info()方法。例如,假设我们有一条额外的消息想显示出来,就使用
String 自变量;而假设没有其他话可说,就不使用。由于为显然相同的概念赋予了两个独立的名字,所以看
起来可能有些古怪。幸运的是,方法过载允许我们为两者使用相同的名字。
4。2。1 区分过载方法
若方法有同样的名字,Java 怎样知道我们指的哪一个方法呢?这里有一个简单的规则:每个过载的方法都必
须采取独一无二的自变量类型列表。
若稍微思考几秒钟,就会想到这样一个问题:除根据自变量的类型,程序员如何区分两个同名方法的差异
呢?
即使自变量的顺序也足够我们区分两个方法(尽管我们通常不愿意采用这种方法,因为它会产生难以维护的
97
…………………………………………………………Page 99……………………………………………………………
代码):
//: OverloadingOrder。java
// Overloading based on the order of
// the arguments。
public class OverloadingOrder {
static void print(String s; int i) {
System。out。println(
〃String: 〃 + s +
〃; int: 〃 + i);
}
static void print(int i; String s) {
System。out。println(
〃int: 〃 + i +
〃; String: 〃 + s);
}
public static void main(String'' args) {
print(〃String first〃; 11);
print(99; 〃Int first〃);
}
} ///:~
两个print()方法有完全一致的自变量,但顺序不同,可据此区分它们。
4。2。2 主类型的过载
主(数据)类型能从一个“较小”的类型自动转变成一个“较大”的类型。涉及过载问题时,这会稍微造成
一些混乱。下面这个例子揭示了将主类型传递给过载的方法时发生的情况:
//: PrimitiveOverloading。java
// Promotion of primitives and overloading
public class PrimitiveOverloading {
// boolean can't be automatically converted
static void prt(String s) {
System。out。println(s);
}
void f1(char x) { prt(〃f1(char)〃); }
void f1(byte x) { prt(〃f1(byte)〃); }
void f1(short x) { prt(〃f1(short)〃); }
void f1(int x) { prt(〃f1(int)〃); }
void f1(long x) { prt(〃f1(long)〃); }
void f1(float x) { prt(〃f1(float)〃); }
void f1(double x) { prt(〃f1(double)〃); }
void f2(byte x) { prt(〃f2(byte)〃); }
void f2(short x) { prt(〃f2(short)〃); }
void f2(int x) { prt(〃f2(int)〃); }
void f2(long x) { prt(〃f2(long)〃); }
void f2(float x) { prt(〃f2(float)〃); }
void f2(double x) { prt(〃f2(double)〃); }
98
…………………………………………………………Page 100……………………………………………………………
void f3(short x) { prt(〃f3(short)〃); }
void f3(int x) { prt(〃f3(int)〃); }
void f3(long x) { prt(〃f3(long)〃); }
void f3(float x) { prt(〃f3(float)〃); }
void f3(double x) { prt(〃f3(double)〃); }
void f4(int x) { prt(〃f4(int)〃); }
void f4(long x) { prt(〃f4(long)〃); }
void f4(float x) { prt(〃f4(float)〃); }
void f4(double x) { prt(〃f4(double)〃); }
void f5(long x) { prt(〃f5(long)〃); }
void f5(float x) { prt(〃f5(float)〃); }
void f5(double x) { prt(〃f5(double)〃); }
void f6(float x) { prt(〃f6(float)〃); }
void f6(double x) { prt(〃f6(double)〃); }
void f7(double x) { prt(〃f7(double)〃); }
void testConstVal() {
prt(〃Testing with 5〃);
f1 (5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);
}
void testChar() {
char x = 'x';
prt(〃char argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testByte() {
byte x = 0;
prt(〃byte argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testShort() {
short x = 0;
prt(〃short argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testInt() {
int x = 0;
prt(〃int argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testLong() {
long x = 0;
prt(〃long argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testFloat() {
float x = 0;
99
…………………………………………………………Page 101……………………………………………………………
prt(〃float argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testDouble() {
double x = 0;
prt(〃double argument:〃);
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
public static void main(String'' args) {
PrimitiveOverloading p =
new PrimitiveOverloading();
p。testConstVal();
p。testChar();
p。testByte();
p。testShort();
p。testInt();
p。testLong();
p。testFloat();
p。testDouble();
}
} ///:~
若观察这个程序的输出,就会发现常数值 5 被当作一个 int值处理。所以假若可以使用一个过载的方法,就
能获取它使用的int值。在其他所有情况下,若我们的数据类型“小于”方法中使用的自变量,就会对那种
数据类型进行“转型”处理。char 获得的效果稍有些不同,这是由于假期它没有发现一个准确的 char 匹
配,就会转型为 int。
若我们的自变量“大于”过载方法期望的自变量,这时又会出现什么情况呢?对前述程序的一个修改揭示出
了答案:
//: Demotion。java
// Demotion of primitives and overloading
public class Demotion {
static void prt(String s) {
System。out。println(s);
}
void f1(char x) { prt(〃f1(char)〃); }
void f1(byte x) { prt(〃f1(byte)〃); }
void f1(short x) { prt(〃f1(short)〃); }
void f1(int x) { prt(〃f1(int)〃); }
void f1(long x) { prt(〃f1(long)〃); }
void f1(float x) { prt(〃f1(float)〃); }
void f1(double x) { prt(〃f1(double)〃); }
void f2(char x) { prt(〃f2(char)〃); }
void f2(byte x) { prt(〃f2(byte)〃); }
void f2(short x) { prt(〃f2(short)〃); }
void f2(int x) { prt(〃f2(int)〃); }
void f2(long x) { prt(〃f2(long)〃); }
void f2(float x) { prt(〃f2(float)〃); }
100
…………………………………………………………Page 102……………………………………………………………
void f3(char x) { prt(〃f3(char)〃); }
void f3(byte x) { prt(〃f3(byte)〃); }
void f3(short x) { prt(〃f3(short)〃); }
void f3(int x) { prt(〃f3( int)〃); }
void f3(long x) { prt(〃f3(long)〃); }
void f4(char x) { prt(〃f4(char)〃); }
void f4(byte x) { prt(〃f4(byte)〃); }
void f4(short x) { prt(〃f4(short)〃); }
void f4(int x) { prt(〃f4(int)〃); }
void f5(char x) { prt(〃f5(char)〃); }
void f5(byte x) { prt(〃f5(byte)〃); }
void f5(short x) { prt(〃f5(short)〃); }
void f6(char x) { prt(〃f6(char)〃); }
void f6(byte x) { prt(〃f6(byte)〃); }
void f7(char x) { prt(〃f7(char)〃); }
void testDouble() {
double x = 0;
prt(〃double argument:〃);
f1(x);f2((float)x);f3((long)x);f4((int)x);
f5((short)x);f6((byte)x);f7((char)x);
}
public static void main(String'' args) {
Demotion p = new Demotion();
p。testDouble();
}
} ///:~
在这里,方法采用了容量更小、范围更窄的主类型值。若我们的自变量范围比它宽,就必须用括号中的类型
名将其转为适当的类型。如果不这样做,编译器会报告出错。
大家可注意到这是一种“缩小转换”。也就是说,在造型或转型过程中可能丢失一些信息。这正是编译器强
迫我们明确定义的原因——我们需明确表达想要转型的愿望。
4。2。3 返回值过载
我们很�