元数据卡
- 前置知识:方法(第5章)、递归(第5章)
- 预计时间:30 分钟
- 阅读模式: 动手实践
- 完成标志:能独立写出方法和递归代码,通过所有验收标准
这一章没有新知识。把你前几节学到的方法和递归用起来。先热身,再挑战,最后找 bug。
热身(5 分钟,必做)
1. 奇偶判断
写一个方法 isEven(int n),返回 true 如果 n 是偶数。在 main 里循环打印 1 到 10 的奇偶判断。
2. 三个数的最大值
写一个方法 max(int a, int b, int c) 返回三个数中最大的。
3. 重载问候
重载 greet 方法:greet(String name) 和 greet(String name, String title),输出不同的问候语。
4. 递归阶乘
用递归写一个方法 int pow(int base, int exp),计算 base^exp。比如 pow(2, 5) = 32。
5. 各位数字之和
用递归写 int sumDigits(int n),计算各位数字之和。比如 sumDigits(123) = 1+2+3 = 6。
6. 倒计时
用递归写 void countdown(int n),倒计时输出 n, n-1, ..., 1, 0, 发射!。
挑战(30 分钟,选做)
1. 老陈牌计算器
写一个程序,定义 add、sub、mul、div 四个方法,从 main 传入两个数,输出四则运算结果。
// 预期输出示例
add(10, 5) = 15
sub(10, 5) = 5
mul(10, 5) = 50
div(10, 5) = 22. 二分搜索(递归版)
给定已排序数组 {1, 3, 5, 7, 9, 11, 13, 15},用递归实现二分查找,返回目标值的索引。如果没找到返回 -1。
3. 文件搜索器
写一个程序,递归遍历整个项目目录,找到所有文件名包含关键词的文件(比如包含 "loop" 的 .java 文件)。打印出它们的完整路径。
4. 斐波那契性能测试
写一个 Benchmark 程序,分别测试普通递归版、记忆化递归版、循环版计算 F(40) 的时间。
F(40) = 102334155
普通递归: 1234ms
记忆化递归: 0ms
循环: 0ms排障(找 Bug)
1. 交换失败
下面这个程序试图交换两个变量,但没有成功。解释为什么,并修复它:
public class Swap {
public static void main(String[] args) {
int a = 5, b = 10;
swap(a, b);
System.out.println("a=" + a + " b=" + b); // 期望 a=10, b=5
}
static void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
}提示:值传递。swap 方法的修改只在它的栈帧里生效。考虑用数组或者在 main 里直接交换。
2. 回文判断
这段代码试图判断"一个字符串是不是回文",但有问题:
public class Palindrome {
public static boolean isPalindrome(String s) {
if (s.length() <= 1) return true;
if (s.charAt(0) != s.charAt(s.length() - 1)) return false;
return isPalindrome(s.substring(0, s.length() - 1)); // 找 bug 在这里
}
public static void main(String[] args) {
System.out.println(isPalindrome("racecar")); // 期望 true
System.out.println(isPalindrome("hello")); // 期望 false
System.out.println(isPalindrome("a")); // 期望 true
}
}提示:递归子调用减少了字符串吗?减少了哪一头?回文的定义是"从两边往里比较",你只砍了一头,会无限循环吗?
观察实验
栈溢出临界点
写一个递归程序(比如计算 1 到 n 的累加),在不同 n 值下运行,观察报 StackOverflowError 的临界点。尝试用以下命令调小栈空间:
java -Xss256k Sum看看栈空间从默认值缩减到 256KB 时,临界 n 值从多少降到多少。
验收标准
- [ ] 你能写出带参数和返回值的方法
- [ ] 你知道
void表示不返回 - [ ] 你能解释"值传递"——为什么
swap(a, b)无法在方法内部交换外部变量 - [ ] 你能画出
A→B→C嵌套调用的调用栈变化 - [ ] 你能解释方法重载的规则(同名、不同参数列表)
- [ ] 你能手写一个简单的递归函数(阶乘、求和)
- [ ] 你能正确解释"基准情况"和"递归情况"的关系
- [ ] 你能画出
factorialRecur(4)的调用栈变化过程 - [ ] 你知道什么情况下递归会栈溢出
旅人笔记
跑步要跑,代码要写。学编程只有一条路:动手写。 先做热身再挑战,遇到 bug 别急——画调用栈、加打印、一步步缩小范围。你和老陈的距离,只是练习的遍数。
→ 下一站:数组
从单兵作战到拆解任务,你已经掌握了一个程序的基本结构——变量、条件、循环、方法和递归。但你要处理的数据越来越多了。一个人的剑谱要记,十个人的呢?一百个人的呢?下一章,我们打开数组的门——它用数字下标就能让你走遍整个数据集合。