1.5 修错、改输出、验证入口
前置知识:本章前四讲
预计时间:30 分钟
练习环境:JDK 17+ 与 Bash;所有文件写入临时目录
完成标志:完成三项必做实验,并保存命令和结果
所有练习都在新目录中进行:
chapter1_lab_root=$(mktemp -d)
readonly chapter1_lab_root
mkdir -p "$chapter1_lab_root/chapter01-lab/out"
cd "$chapter1_lab_root/chapter01-lab"删除或重建产物时,只操作这里的 out。
必做一:修复三类编译错误
保存为 Bug.java:
public class Bug {
public static void main(String[] args) {
system.out.println("Hello, Java!")
System.Out.println("Hello Coder!");
}
}先原样编译:
javac -d out Bug.java把第一条诊断记录下来,然后依次修复:
- 第一条调用末尾的英文分号;
system的大小写;Out的大小写。
每改一处就重新编译。最终运行:
java -cp out Bug预期输出:
Hello, Java!
Hello Coder!注意:一处语法错误可能引发多条连锁诊断,因此初始错误数量未必正好等于源码中的独立根因数量。
必做二:观察重新编译
保存为 Greeting.java:
public class Greeting {
public static void main(String[] args) {
System.out.println("version one");
}
}javac -d out Greeting.java
java -cp out Greeting把源码改为 version two,但先不要编译,直接运行一次。你应仍看到 version one。随后重新编译再运行,输出才会变成 version two。
在实验记录中写一句解释:java 运行的是哪一个文件?
必做三:使用命令行参数
保存为 Greeter.java:
public class Greeter {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Hello, user!");
return;
}
System.out.println("Hello, " + args[0] + "!");
}
}编译后运行两次:
javac -d out Greeter.java
java -cp out Greeter
java -cp out Greeter Lin预期输出:
Hello, user!
Hello, Lin!你还没系统学习 if 和数组,当前只需确认:启动命令中类名之后的词会进入 args。
选做一:print、println 与转义序列
public class Lines {
public static void main(String[] args) {
System.out.print("north ");
System.out.println("gate");
System.out.println("line 1\nline 2");
System.out.println("A\tB");
}
}在运行前先写下你预测的四行结果,再编译验证。终端对制表符的显示宽度可能不同,所以只检查 A 与 B 之间存在制表间隔。
选做二:入口方法可以重载吗
保存为 EntryPoints.java:
public class EntryPoints {
public static void main(String[] args) {
System.out.println("launcher entry");
main(3);
}
public static void main(int count) {
System.out.println("overload: " + count);
}
}它可以编译,因为两个方法参数类型不同,属于重载。Java 启动器只选择字符串数组形式的传统入口,main(int) 是程序自己调用的普通重载。
现在复制一份 main(String[] args),保持签名完全相同。编译器会拒绝同一类中的重复方法。把“同名”和“同签名”区分开。
选做三:清理产物后再验证
pwd
test ! -e out || rm -r -- out
mkdir out
javac -d out Greeter.java
java -cp out Greeter Ada这能证明结果不依赖旧产物。pwd 必须显示当前实验目录;不要在不确定位置时运行递归删除。
实验记录模板
| 实验 | 原始命令 | 第一条关键诊断或输出 | 修改 | 复验结果 |
|---|---|---|---|---|
| Bug | ||||
| 重新编译 | ||||
| 参数 |
验收与清理
确认 Bug.java 得到两行输出,亲自观察过旧字节码仍会运行,并让 Greeter 的无参数、有参数两条路径都通过。实验记录保留到需要的位置后,删除临时目录:
cd
ls -ld -- "$chapter1_lab_root"
rm -r -- "$chapter1_lab_root"错误本身不会自动教人;记录命令、阶段、第一条诊断和产物位置,再复验一次,才会把问题缩小。