5.8 实验:方法、值传递与重载
前置知识:方法声明、参数、返回值、调用栈和重载
预计时间:50 分钟
练习环境:JDK 17+ 与 Bash;所有文件写入临时目录
完成标志:完成四项必做实验并解释调用契约
chapter5_lab_root=$(mktemp -d)
readonly chapter5_lab_root
mkdir -p "$chapter5_lab_root/chapter05-lab/out"
cd "$chapter5_lab_root/chapter05-lab"必做一:纯计算方法
保存为 NumberTools.java:
public class NumberTools {
static boolean isEven(int value) {
return value % 2 == 0;
}
static int maxOfThree(int first, int second, int third) {
return Math.max(first, Math.max(second, third));
}
static int digitSum(int value) {
long remaining = Math.abs((long) value);
int sum = 0;
do {
sum += (int) (remaining % 10);
remaining /= 10;
} while (remaining > 0);
return sum;
}
public static void main(String[] args) {
System.out.println(isEven(-4));
System.out.println(maxOfThree(3, 9, 5));
System.out.println(digitSum(-2147483648));
}
}javac -d out NumberTools.java
java -cp out NumberTools预期为 true、9、47。digitSum 先转 long 再取绝对值,避开 Math.abs(Integer.MIN_VALUE) 仍为负数的边界。
必做二:证明值传递
保存为 PassingLab.java:
import java.util.Arrays;
public class PassingLab {
static void changePrimitive(int value) {
value = 99;
}
static void mutateArray(int[] values) {
values[0] = 99;
}
static void replaceArray(int[] values) {
values = new int[] {7, 8};
}
public static void main(String[] args) {
int count = 1;
int[] numbers = {1, 2};
changePrimitive(count);
mutateArray(numbers);
replaceArray(numbers);
System.out.println(count);
System.out.println(Arrays.toString(numbers));
}
}javac -d out PassingLab.java
java -cp out PassingLab预期:
1
[99, 2]用“复制了什么值、两个变量是否标识同一对象”解释,不使用“数组是引用传递”这句错误捷径。
必做三:重载解析
保存为 OverloadLab.java:
public class OverloadLab {
static String pick(long value) {
return "long";
}
static String pick(Integer value) {
return "Integer";
}
static String pick(int... values) {
return "varargs";
}
static String describe(Object value) {
return "object";
}
static String describe(String value) {
return "string";
}
public static void main(String[] args) {
Object value = "iron";
System.out.println(pick(1));
System.out.println(pick());
System.out.println(describe(value));
System.out.println(describe("iron"));
}
}javac -d out OverloadLab.java
java -cp out OverloadLab预期:long、varargs、object、string。记录每个调用点的实参声明类型和适用阶段。
必做四:栈轨迹
保存为 TraceLab.java:
public class TraceLab {
static void loadOrder() {
parseQuantity();
}
static void parseQuantity() {
Integer.parseInt("many");
}
public static void main(String[] args) {
loadOrder();
}
}javac -d out TraceLab.java
trace_status=0
java -cp out TraceLab || trace_status=$?
test "$trace_status" -ne 0运行应以非零状态结束并打印 NumberFormatException。从 parseQuantity、loadOrder 到 main 标记业务调用链;错误消息和 JDK 内部帧可能随版本变化。
选做一:有界递归
static long factorial(int value) {
if (value < 0) {
throw new IllegalArgumentException("negative value");
}
if (value > 20) {
throw new ArithmeticException("factorial exceeds long: " + value);
}
if (value <= 1) {
return 1L;
}
return Math.multiplyExact(value, factorial(value - 1));
}测试 0、1、5、20、21 和 -1。21 的阶乘超出 long,输入检查会立即报告;负数则违反阶乘的输入域。再传入 Integer.MAX_VALUE,确认它也在递归前被拒绝。
选做二:把默认参数集中
static String describeItem(String name) {
return describeItem(name, 1, false);
}
static String describeItem(String name, int level) {
return describeItem(name, level, false);
}
static String describeItem(String name, int level, boolean rush) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name is blank");
}
if (level < 1) {
throw new IllegalArgumentException("level: " + level);
}
return name + ":" + level + ":" + rush;
}验证所有重载都走同一校验。再思考 rush 是否应改为枚举。
故障实验
逐个打开并记录第一条诊断:
// static int convert(int value) { return value; }
// static long convert(int number) { return number; } // 只改返回类型// static void print(String value) { }
// static void print(Integer value) { }
// print(null); // 歧义// static int missingReturn(boolean flag) {
// if (flag) return 1;
// }区分重复签名、重载歧义和正常路径缺少返回值。
安全清理
pwd
test ! -e out || rm -r -- out确认位于本实验目录,只删除本章产物。
验收与清理
给纯计算方法补上零和负数用例,并保留 Integer.MIN_VALUE 用例,数组实验能用“引用值副本”解释,四个重载调用都能说出选择阶段。栈轨迹要从异常暴露点一路还原到 main,三类故障则分别标成重复签名、调用歧义和缺少返回路径。保存记录后清理临时目录:
cd
ls -ld -- "$chapter5_lab_root"
rm -r -- "$chapter5_lab_root"方法与递归的路径都已验过,下一章把一组同类型值放进连续的索引空间。
→ 下一步:数组入门