方法(函数)
这是什么:方法(Method) = 把一段代码打包、起个名字,要用时喊一声,一次编写到处调用。
为什么用:代码写多了会发现,同一段逻辑到处复制粘贴,改一次得翻遍全文件。方法就像一台榨汁机:投进去水果,咔咔一顿转,倒出果汁;机器造一次,全家能用一年。
如何用:本章先学定义与调用,再练方法重载和变量作用域,最后弄清「参数只传复印件」这条 Java 规矩。
定义与调用
先照抄 main 的写法:public static 开头(这两个词的原理属于面向对象篇,现在照着写就行)。
public class MethodDemo {
public static void main(String[] args) {
greet("小明"); // 调用方法:喊名字 + 给参数
greet("小红");
int total = add(3, 5); // 有返回值的方法,可以用变量接住
System.out.println("3 + 5 = " + total);
}
// 无返回值:void,只干活不交结果
static void greet(String name) {
System.out.println("你好," + name + "!");
}
// 有返回值:int,干完活把结果交出去
static int add(int a, int b) {
return a + b;
}
}
输出:
你好,小明!
你好,小红!
3 + 5 = 8
| 组成 | 例子 | 说明 |
|---|---|---|
| 参数 | (String name) |
干活需要的原料,可以没有 |
| 返回值类型 | void / int |
void 表示不交结果;其他类型必须 return |
return |
return a + b; |
把结果交出去,方法立刻结束 |
把一个方法的"解剖图"完整标一遍,以后照着认:
| 部位 | static int add(int a, int b) |
干什么的 |
|---|---|---|
| 修饰符 | static |
入门阶段照抄(面向对象篇揭晓) |
| 返回类型 | int |
承诺交回来的成品类型 |
| 方法名 | add |
调用时喊的名字,小驼峰 |
| 参数列表 | (int a, int b) |
原料清单:类型 + 名字,成对出现 |
| 方法体 | { return a + b; } |
真正的干活逻辑 |
调用时还有两个术语要对上号:定义时写的 a、b 叫形参(形式参数,占位用的),调用时给的 3、5 叫实参(实际参数,真材实料)。实参按位置一一对应塞给形参——第一个给第一个,第二个给第二个。
执行流程也值得在脑子里过一遍电影:程序在 main 里走到 add(3, 5),跳进 add 方法执行,return 把 8 交回来,跳回 main 原地继续往下走。方法就像"暂时离题去办件事,办完带着结果回来"。
方法重载:同名不同活
Java 允许方法名相同、参数不同的方法共存,这叫重载(overload):
static int add(int a, int b) { // 两个 int 参数
return a + b;
}
static double add(double a, double b) { // 参数类型不同,算重载
return a + b;
}
static int add(int a, int b, int c) { // 参数个数不同,也算重载
return a + b + c;
}
调用 add(1, 2) 走第一个,add(1.5, 2.5) 走第二个——Java 按你给的参数自动匹配。你天天在用的 System.out.println 能打印各种类型,就是靠一堆重载实现的。
重载的好处:一个动作一个名字。"加"就是 add,不管加的是 int 还是 double,不用记 addInt、addDouble 两个名字——调用者只管"我要加",类型匹配的杂活交给编译器。
重载的判定规则要划三条重点线:
| 情况 | 算不算重载 |
|---|---|
| 参数类型不同 | ✅ 算 |
| 参数个数不同 | ✅ 算 |
| 只有返回值类型不同,参数完全一样 | ❌ 不算,编译报错 |
第三条最容易想岔:返回值是"结果",不是"身份"。光改返回类型,Java 在你调用 add(1, 2) 时根本不知道该去挑哪个,所以直接禁止这种重载。
更多方法练习
// 把摄氏度转成华氏度
static double celsiusToFahrenheit(double c) {
return c * 1.8 + 32;
}
// 返回两个数中较大的那个
static int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}
// 不传参数的问候
static void greet() {
System.out.println("你好,陌生人!");
}
调用示例:
public static void main(String[] args) {
System.out.println(celsiusToFahrenheit(37)); // 98.6
System.out.println(max(3, 7)); // 7
greet(); // 你好,陌生人!
}
max 这个写法有个细节:两个 return 各管一边。a > b 成立就交出 a,方法立刻结束——所以后面那行 return b 只在不成立时才轮到执行。也有人喜欢写成三元一行流 return a > b ? a : b;,效果相同,挑顺眼的用。
方法里当然还能调用别的方法,方法调方法是搭积木的基本玩法:
// 判断是否及格,复用了上面的思想
static boolean isPass(int score) {
return score >= 60; // 比较表达式本身就是 boolean,直接交出去
}
注意 return score >= 60;——比较的结果就是 boolean,不用画蛇添足写 if 再 return true/false。让代码说短话,是方法章给你的第一个审美训练。
变量作用域:谁看得见谁
方法内声明的变量叫局部变量,只在本方法的大括号内有效:
static void methodA() {
int x = 1;
System.out.println(x); // ✅ x 活在 methodA 里
}
static void methodB() {
System.out.println(x); // ❌ 编译报错,B 家没有 x 这个人
}
参数也是局部变量:形参 a、b 只活在 add 方法里,出了大括号就"下线"。不同方法里的同名变量互不相干——methodA 里有个 x,methodB 里也可以有个 x,它们是两个不同盒子。记住一条:变量活在自己所在的那对大括号里,流程控制章循环变量 i 出了循环就消失,也是同一条规则。
参数传递:Java 只传"复印件"
一个重要事实:把变量传进方法,方法内改它,外面的原值不变——Java 传的是值的复印件:
public class PassDemo {
static void tryChange(int n) {
n = 999; // 改的只是复印件
}
public static void main(String[] args) {
int num = 1;
tryChange(num);
System.out.println(num); // 还是 1
}
}
输出:
1
tryChange 收到的是 num 的一份拷贝,撕拷贝不影响原件。想"改了真能生效",就让方法返回新值,调用方接住重新赋值——这是入门阶段最清爽的思路。引用类型(如数组)传的虽然也是"复印件",但复印件上抄的是地址,所以能顺着地址改到原件内容,这层进阶理解放到面向对象篇再展开。
❓ 常见问题
Q1:方法一定要有返回值吗?
不是。返回值类型写 void 表示不返回任何东西,方法里只干活不交成品。
Q2:方法里能定义方法吗?
不能。Java 方法不能嵌套定义(除了局部类,进阶话题)。所有方法都写在类级别。
Q3:return 后面还能写代码吗?
可以写,但永远不会执行——return 后方法立刻结束,后面的代码是"死代码",编译器通常会警告。
Q4:main 方法为什么长成那个固定样子?
它是 JVM 钦点的程序入口,签名必须严格是 public static void main(String[] args),JVM 才认。你现在只需要知道:void 表示入口方法不交结果,String[] args 是命令行参数,其余交给面向对象篇。
Q5:什么是递归?现在要学吗?
方法调用自己就叫递归,比如"算 n 的阶乘 = n × (n-1) 的阶乘"。它优雅但烧脑,还容易写出自嘲式死循环,入门阶段知道有这回事即可,等你方法写得熟了再回头玩它。
⚠️ 新手翻车现场
翻车一:void 方法试图 return 一个值
static void sayHi() {
return "你好"; // ❌ void 方法不能返回值
}
问题:void 表示不返回任何东西,return 后面不能跟值。
修正:改成 static String sayHi() { return "你好"; }。
翻车二:方法参数类型不匹配
static int add(int a, int b) => a + b;
add(3, "5"); // ❌ 编译报错:不能将 String 转换为 int
问题:Java 是强类型,参数类型必须严格匹配。
修正:add(3, 5),两个都是 int。
翻车三:有返回值的方法忘了 return
static int add(int a, int b) {
a + b; // ❌ 算了但没交出来,编译报错 "missing return statement"
}
问题:声明返回 int 的方法,必须有 return 把 int 交出去。
修正:return a + b;。
翻车四:指望方法改外面的变量
static void addOne(int n) {
n = n + 1;
}
public static void main(String[] args) {
int count = 10;
addOne(count);
System.out.println(count); // 打印 10,不是 11!
}
问题:值传递——方法里改的是复印件,count 原件分毫不动。程序不报错,但结果和预期不符,属于"安静的 bug",比编译错误更磨人。
修正:让方法返回新值:count = addOne(count);,把"返回类型 int"配上 return n + 1;。
翻车五:重载只改了返回类型
static int calc(int a) { return a; }
static double calc(int a) { return a; } // ❌ 编译报错:重复的方法
问题:两个方法名相同、参数完全相同,只有返回类型不同——这不构成重载,编译器无法区分调用谁。
修正:重载必须"参数列表长得不一样",或者干脆起不同的方法名。
🎯 什么时候用方法
- 一段代码要被用两次及以上
- 需要给代码起个有意义的名字,让
main更易读 - 想把复杂逻辑拆成小块,逐个测试
再加一条黄金判断法:当 main 读起来像流水账、超过一屏时,就该拆方法了。好的程序像目录——main 里一行一个动作("读输入、算结果、打报告"),细节都藏在名字起得清楚的方法里。别人读你的代码像读大纲,而不是像考古。
📝 本章小结
- 方法 = 返回类型 + 方法名 + 参数列表 + 方法体
void表示不返回值;其他类型必须return- 形参是占位、实参是真料,按位置一一对应;Java 是值传递,方法内改参数不影响外面
- 方法重载:同名不同参可共存,编译器按参数类型和个数挑选;只改返回值不算重载
- 变量活在自己所在的大括号里,方法之间看不见彼此的局部变量
return后方法立刻结束,后面代码不会执行- 记忆口诀:方法 = 名字 + 原料(参数)+ 成品(返回值);同名不同参,就是重载。
记忆锚点:方法是台自动贩卖机——按钮名是方法名,投币口是参数,出货口是返回值;投币规格不对机器不认(类型匹配),按了按钮不拿货白按(返回值要接住),void 机器只出声不出货。
动手改
- 写一个
static double celsiusToFahrenheit(double c),把摄氏度转华氏度(公式c * 1.8 + 32) - 给
greet加一个重载版本:不传参数时说"你好,陌生人!" - 写一个
static int max(int a, int b),返回两个数中较大的那个 - 把
celsiusToFahrenheit(37)的结果打印出来,验证是 98.6 - 写
static boolean isPass(int score),并在 main 里用 59 和 60 各验证一次 - 写
static void printLine(int n),打印 n 个星号(循环拼接),体会 void 方法的用法
下一章:字符串,玩转最常用的数据 🐸