Java 中的作用域
写一个带一个参数的方法,名叫 mark:static void mark(int n)。在花括号里用 System.out.println(n); 打印这个参数。从 main 调用 mark(4);。屏幕应显示一行:4。名字 n 只存在于 mark 内部。若试图从 main 打印 n,javac 会拒绝。这条边界——方法能看见哪些名字——就是本页要教的内容。
留在方法里的名字
在重载那一页,几个 paint 方法共用一名,但参数列表分开。这里焦点更小:一个方法、一个参数名,以及这个名字允许出现在哪里。参数是属于声明它的那个方法的名字。出了该方法的花括号,这个名字就不存在了。
新建一个小程序文件,名叫 Gate.java。第一行的 public class 必须与文件名一致:public class Gate。不要在这个文件里留下旧的 Sign 或 Box 类名;编译器要求类名与文件名一致。
在 main 外面、仍在类的花括号里,写 static void mark(int n)。方法体只有一次打印:System.out.println(n);。本页保持 void。你在观察可见性,不是返回值。编译前先保存文件。完整的第一个程序在下一个代码框里。
带 mark 的 Gate.java
这是你先编译的版本。main 里放调用。mark 里放使用 n 的打印。
public class Gate {
public static void main(String[] args) {
mark(4);
}
static void mark(int n) {
System.out.println(n);
}
}
在存放 Gate.java 的文件夹里运行 javac Gate.java。当圆括号、花括号和分号都匹配时,javac 自己不会写出一行。然后运行 java Gate——不要写成 java Gate.java。第二个命令去掉 .java 后缀。这两条命令在 Windows 和 macOS 上都一样。程序应打印一行后停止:4。它不应等待你输入。如果终端在等键盘输入,说明文件里还留着旧练习的 nextLine 调用。删掉它,只保留上面的 mark(4); 和 mark 方法。
按顺序把这次运行走一遍。Java 从 main 开始。调用 mark(4) 把 4 送进参数 n。在 mark 里,println(n) 写出 4。当 mark 结束时,名字 n 也结束了。main 从未持有过名字 n。数字 4 作为值穿过了这次调用。名字 n 并没有搬进 main。
若在调用之后于 main 里加上 System.out.println(n);,javac 会报告找不到符号 n。这个错误就是这堂课:n 从未在 main 里声明。删掉 main 里那一行来修好,或者若你需要本地名字,就在 main 声明另一个名字。不要指望 mark 的参数会自己出现在 main 里。
参数旁边的本地名字
在 mark 里你也可以声明一个不是参数的新名字。那个本地名字只活在 mark 的花括号之间。改方法体去存一个标签,并在一行打印标签和 n,或另留一个短方法做演示——本页下一个代码框改为演示从 main 传入名字,这是初学者更常见的路径。
初学者常希望:在 main 里声明的名字会自动出现在类的每个方法里。在这个入门形状上并非如此。若 main 有 int room = 4;,而 mark 在未接收的情况下打印 room,javac 在 mark 里找不到 room。正确做法是传值:mark(room);,同时 mark 仍声明为 mark(int n)。
把 main 的本地名字传给 mark
在 main 里声明 int room = 4;。调用 mark(room);。在 mark 里继续打印 n。屏幕仍显示 4。main 里的本地名字是 room。mark 里的参数名是 n。它们是不同位置上的不同名字。旅行的是值 4。
public class Gate {
public static void main(String[] args) {
int room = 4;
mark(room);
}
static void mark(int n) {
System.out.println(n);
}
}
再次编译运行:javac Gate.java,然后 java Gate。你仍看到一行:4。若把 room 改成 9 且不动方法体,屏幕显示 9。方法仍打印到达 n 的值。若在 main 加上 System.out.println(room);,main 也可以打印 room——那个名字属于那里。main 仍然不能打印 n。
若 mark 声明自己的本地名字——例如在花括号里写 int tag = 1;——这个 tag 对 main 不可见。在 main 里尝试 System.out.println(tag); 会失败,原因与从 main 打印 n 相同。mark 的花括号对其中声明的名字是一堵墙。
墙在保护什么
用平常话读这段分界。在 main 声明的名字留在 main,除非你把它们的值放进调用。在 mark 声明的名字——参数与本地——留在 mark。调用携带的是值,不是名字本身。上一页的重载是另一项技能:多个方法共用一个方法名。作用域讲的是变量或参数名在源码里允许出现在哪里。
残留的 Sign 演示若仍带多个 paint 方法,且 main 还在调用 paint("ok"),会把屏幕弄乱。把 main 清到你正在测试的 mark 调用。不要把 mark 嵌进 main 的花括号里。方法放在类里、与 main 并列。
在 main 写 System.out.println("n"); 只会打印引号里的字母 n。它不会打印参数。当你要的是通过调用传来的值时,把 println(n) 留在 mark 里。若方法头仍是 mark(int n),写成空括号的 mark(); 会失败——调用必须送入一个 int,无论是字面量 4 还是本地名字 room。
进入 recursion 之前
你可以写 mark(int n),在该方法内打印 n,并把 n 留在 main 之外。你可以在 main 声明 room,并把 room 传给 mark。屏幕显示穿过调用的那个值。名字不会自己从花括号里漏出去。下一页是 recursion;方法会用更小的实参调用自己,直到停止条件结束整条链。
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部