正在加载...

Java 中的重载

在同一个类里放两个都叫 paint 的方法。一个方法头是 static void paint(String word)。另一个是 static void paint(int n)。方法体很短:第一个打印 word,第二个打印 n。在 main 里先调用 paint("ok");,再调用 paint(3);。屏幕应显示两行:先是 ok,再是 3。Java 不会把第二个 paint 当成冲突。它把两个方法头看成不同方法,因为参数列表不同。这种同名、不同列表,就是本页要教的内容。

同名,不同列表

到目前为止,每个新想法都用新方法名:ring、greet、twice。这里故意让名字保持 paint。变化的是圆括号里的内容。一个列表放 String。另一个列表放 int。编译器会保留两者,因为这些列表并不相同。
新建一个小程序文件,名叫 Sign.java。第一行的 public class 必须与文件名一致:public class Sign。不要在这个文件里留下旧的 Box 或 Tip 类名;编译器要求类名与文件名一致。
在 main 外面、仍在类的花括号里,写上两个 paint 方法头。本页保持 void:每个方法体都打印,不需要通过 return 把值交回 main。第一个方法体用 System.out.println(word);。第二个用 System.out.println(n);。编译前先保存文件。完整的第一个程序在下一个代码框里。

带两个 paint 方法的 Sign.java

这是你先编译的版本。main 里有两次调用。类里有两个共用一名的 paint 方法。

paint String and paint int

java
public class Sign {
    public static void main(String[] args) {
        paint("ok");
        paint(3);
    }

    static void paint(String word) {
        System.out.println(word);
    }

    static void paint(int n) {
        System.out.println(n);
    }
}

在存放 Sign.java 的文件夹里运行 javac Sign.java。当圆括号、花括号和分号都匹配时,javac 自己不会写出一行。然后运行 java Sign——不要写成 java Sign.java。第二个命令去掉 .java 后缀。这两条命令在 Windows 和 macOS 上都一样。程序应打印两行后停止:先是 ok,再是 3。它不应等待你输入。如果终端在等键盘输入,说明文件里还留着旧练习的 nextLine 调用。删掉它,只保留上面的两次 paint 调用和两个 paint 方法。
按顺序把这次运行走一遍。Java 从 main 开始。第一次调用是 paint("ok")。实参是 String,所以 Java 运行接收 String word 的方法体,并打印 ok。第二次调用是 paint(3)。实参是 int,所以 Java 运行接收 int n 的方法体,并打印 3。两次名字都是 paint。圆括号里的列表决定跑哪一段方法体。
如果两行都是 ok,你可能只留下了 String 方法,并且每次调用都打印固定单词。如果两行都是 3,你可能只留下了 int 方法。两个方法头都要保留。如果 javac 报告 paint 已经定义过,检查两个方法头是否是同一份列表——例如两份 paint(String word)。重载需要列表真正不同,不能只是同一方法头换个参数名再写一遍。

带两个词的第二份列表

参数个数也可以不同。再加第三个重载:接收两个 String,并在一行里用空格打印它们。前两个 paint 方法先留着。在 main 里于前面的调用之后调用新形状,或者新建一个只练习这个形状的 main。

paint two Strings

java
public class Sign {
    public static void main(String[] args) {
        paint("hi", "sam");
    }

    static void paint(String a, String b) {
        System.out.println(a + " " + b);
    }
}

保存后再编译运行:javac Sign.java,然后 java Sign。屏幕应显示一行:hi sam。这次调用有两个实参。方法有两个参数。这份匹配就够让 Java 选中这个方法体。若同一类里还有更早的 paint(String word) 和 paint(int n),可以保留。带两个 String 的调用不会选只有一个 String 参数的方法,因为个数不同。
练习时若把三个重载放进同一个文件,main 可以每行调用一种形状。一个 String 的调用仍会走到 paint(String word)。一个 int 的调用仍会走到 paint(int n)。两个 String 的调用会走到 paint(String a, String b)。共用的名字不会抹掉这些区别。

空列表与 String 列表并排

空圆括号的方法也是不同的列表。你可以在 paint(String word) 旁边保留无参数的 paint()。空调用 paint(); 会跑空列表的方法体。调用 paint("go"); 会跑 String 方法体。

paint empty and paint String

java
public class Sign {
    public static void main(String[] args) {
        paint();
        paint("go");
    }

    static void paint() {
        System.out.println("ready");
    }

    static void paint(String word) {
        System.out.println(word);
    }
}

执行 javac Sign.java 和 java Sign 之后,屏幕第一行应是 ready,第二行应是 go。第一次调用圆括号里什么都没有,因此匹配 paint()。第二次送入一个 String,因此匹配 paint(String word)。把其中一个改名为 paintReady 也能编译,但那是另一项技能。本页保留名字 paint,让列表来承担差别。

哪次调用跑哪个方法头

把调用和方法头对照着读。调用里的实参列表必须匹配方法头里的参数列表。在这个入门形状里,类型和个数都重要。

📊 call beside matching paint

main 中的调用 实际运行的方法头 屏幕行
paint("ok"); paint(String word) ok
paint(3); paint(int n) 3
paint("hi", "sam"); paint(String a, String b) hi sam
paint(); paint() ready

常见混淆是写两个都叫 paint(String word) 的方法,并指望第二个算重载。只把参数名改成 paint(String label),对编译器来说并不是新列表。这里要紧的是类型和个数。另一种混淆是调用 paint(true),却从未写过 boolean 参数列表。那时 javac 找不到匹配的 paint。补上接收你想要类型的方法头,或把调用改成你已经支持的类型。
在 main 里写 System.out.println("paint"); 只会打印单词 paint。它不会调用任何方法。当你要接收 String 的那个重载时,保留 paint("ok");。若旧的 Box 文件里的 twice 还留在 Sign.java,而 main 仍打印 twice(7),屏幕会乱。把 main 清到你正在测试的 paint 调用,并只保留这次运行需要的 paint 重载。
不要把 paint 方法嵌进 main 的花括号里。方法放在类里、与 main 并列。两个重载是同一类体里的两个并列方法。

进入 scope 之前

你可以在同一个类里保留一个方法名和多份参数列表。Java 根据调用的实参列表选择方法体。屏幕显示匹配方法体打印的那一行。两份相同列表的方法头不是重载。下一页是 scope;你会看到哪些名字在方法内可见,哪些留在外面。

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
5
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部