【java基础语法】------方法
1. 什么是方法
在 Java 编程中,方法(Method)是程序中最小的执行单元。它是一段用于完成特定功能的代码块,可以被多次调用,是实现程序逻辑的基本构建模块。
我们每天写的 main 方法就是最典型的方法之一:
public static void main(String[] args) {System.out.println("HelloWorld");System.out.println("HelloWorld");
}
这段代码被封装在一个名为 main 的方法中,它是程序的入口点,也是整个程序运行的起点。这说明:一个完整的 Java 程序,是由多个方法组成的。
2. 为什么需要方法?
在实际开发中,我们经常会遇到以下场景:
- 某段代码需要重复执行;
- 某个功能独立且完整,如“发射炮弹”、“登录验证”、“计算总和”等。
这时候,就可以将这些重复或独立的功能提取出来,封装成一个方法,就像把一段代码“打包”进一个盒子中。
举个例子:
在《植物大战僵尸》游戏中,豌豆射手、寒冰射手、玉米投手都会发射炮弹。如果每个角色都写一遍“发射”的20行代码,那不仅冗余,还难以维护。正确做法是:将“炮弹发射”这段代码封装成一个方法,所有植物只需调用这个方法即可,既减少了重复,又方便统一修改。
3. 方法的定义与调用

3.1 最简单的方法
3.1.1 定义格式
public static void 方法名() {// 方法体:实现具体功能的代码
}
3.1.2 调用方式
方法名();
3.1.3 示例:定义一个打游戏的方法
public static void playGame() {System.out.println("选人物");System.out.println("准备开局");System.out.println("对线");System.out.println("崩盘");System.out.println("骂队友");System.out.println("送人头");System.out.println("GG");
}
调用方式:
playGame(); // 执行一次打游戏流程
playGame(); // 再执行一次,无需重复写代码
关键点:
- 方法必须先定义,再调用;
- 括号
()表示这是一个方法,不是变量或表达式;void表示该方法不返回任何值(后面会讲)。
3.2 带参数的方法
有些功能需要外部提供数据才能完成,比如“求两个数的和”。这时就需要使用带参数的方法。
3.2.1 定义格式
public static void 方法名(参数类型 参数名, 参数类型 参数名) {// 方法体:使用参数进行计算或处理
}
3.2.2 重点概念:形参 vs 实参
| 名称 | 全称 | 出现位置 | 说明 |
|---|---|---|---|
| 形参 | 形式参数 | 方法定义中 | 是方法接收数据的“占位符” |
| 实参 | 实际参数 | 方法调用中 | 是调用时传入的具体值或变量 |
示例对比:
// 方法定义 —— 形参是 num1 和 num2
public static void getSum(int num1, int num2) {int result = num1 + num2;System.out.println("两数之和为:" + result);
}// 方法调用 —— 实参是 10 和 20,或变量 a 和 b
getSum(10, 20); // 实参为字面量
int a = 10, b = 20;
getSum(a, b); // 实参为变量
调用规则:
- 实参数量、类型、顺序必须与形参一一对应;
- 否则编译器会报错。
3.2.3 带参数方法的完整格式总结
| 类型 | 格式 | 示例 |
|---|---|---|
| 单个参数 | public static void 方法名(参数类型 参数名) | method(int number) |
| 多个参数 | public static void 方法名(参数1, 参数2, ...) | getSum(int num1, int num2) |
注意:
- 参数之间用逗号分隔;
- 每个参数包含“类型 + 名称”;
- 方法调用时,实参可以是常量、变量或表达式。
3.2.3 方法定义的核心逻辑
定义方法前,问自己两个问题:
- 我要干什么? → 确定方法名和功能;
- 我干这件事需要什么才能完成? → 判断是否需要参数,以及需要哪些参数。
3.3 带返回值的方法
3.3.1 什么时候需要返回值?
当你在调用方法时,需要根据该方法的执行结果来决定下一步操作,就应使用带返回值的方法。
例如:
- 求两个数的和,然后判断是否大于100;
- 判断用户年龄是否合法,再决定是否允许登录;
- 计算商品总价,再进行折扣计算。
这类场景下,不能只靠 System.out.println() 打印结果,而必须让方法“返回”一个值供主程序使用。
3.3.2 定义格式
public static 返回值类型 方法名(参数) {// 方法体:执行具体逻辑return 返回值;
}
关键说明:
返回值类型:表示方法执行完成后要返回的数据类型,如int,double,String,boolean等;return:关键字,用于结束方法并返回指定值;- 返回值必须与声明的返回值类型一致。
示例:定义一个求两数之和的方法
public static int getSum(int a, int b) {int c = a + b;return c; // 返回计算结果
}
注意:
- 如果方法没有
return语句,编译器会报错;void类型的方法不能有return值(除非写return;表示提前结束)。
3.3.3 调用方式
带返回值的方法有三种常见调用方式:
| 调用方式 | 格式 | 说明 |
|---|---|---|
| 直接调用 | 方法名(实参); | 不接收返回值,仅执行方法体(不推荐) |
| 赋值调用 | 变量名 = 方法名(实参); | 将返回值存入变量,便于后续使用 |
| 输出调用 | System.out.println(方法名(实参)); | 直接将返回值打印到控制台 |
示例演示:
public static void main(String[] args) {// 方式一:直接调用(不建议)getSum(10, 20); // 结果丢失了!// 方式二:赋值调用(推荐)int result = getSum(10, 20);System.out.println("和为:" + result);// 方式三:输出调用System.out.println("和为:" + getSum(30, 40));
}
提示:
- 若需多次使用结果,优先选择 赋值调用;
- 若只需查看结果,可使用 输出调用。
3.3.4 总结:为什么要有返回值?
为什么要用带返回值的方法?
因为它实现了“结果复用”和“逻辑解耦”。
- 无返回值方法:只能输出,不能参与其他计算;
- 带返回值方法:能将结果“带回”,支持更复杂的业务逻辑。
4. 方法的注意事项
4.1 return 关键字的使用规则
return 是控制方法执行流程的重要语句,其使用方式取决于方法是否有返回值。
| 情况 | 规则 |
|---|---|
| 无返回值(void)方法 | 可以省略 return;若书写,则只能写 return;(不带值),表示结束方法 |
| 有返回值方法 | 必须包含 return 语句,并且必须返回对应类型的值 |
4.2 方法的调用机制
- 方法不调用就不会执行
即使方法已经定义,只要没有被调用,JVM 不会执行其中的任何代码。
public static void main(String[] args) {// 不调用 showInfo(),它不会运行// showInfo(); // 注释掉,不执行
}public static void showInfo() {System.out.println("信息展示"); // 这行永远不会输出
}
-
方法之间是平级关系,不能互相嵌套定义
Java 中不允许在一个方法内部定义另一个方法(如 C 语言中的嵌套函数)。错误写法:
public static void method1() {public static void method2() { } // 错误!不能嵌套定义
}
正确做法:所有方法都直接写在类中,彼此独立。
4.3 方法的编写顺序与执行顺序无关
Java 中方法的定义顺序不影响执行顺序。程序从 main 方法开始执行,其他方法只有在被调用时才会运行。
示例:
public static void main(String[] args) {greet(); // 调用下面的方法
}public static void greet() {System.out.println("你好!");
}// 这个方法写在最后,也能正常调用
public static void bye() {System.out.println("再见!");
}
即使 greet() 写在 main() 之后,也能成功调用——因为 JVM 在编译时已将所有方法加载到内存中。
4.4 void 类型方法的特殊处理
- 当方法返回值类型为
void时,表示该方法不返回任何值; - 此时可以省略
return语句; - 如果写了
return,后面不能跟具体数据,只能写return;。
合法写法:
public static void printMsg() {System.out.println("消息");return; // 可选,表示结束方法
}
4.5 return 语句后的代码无效
一旦执行到 return 语句,方法立即结束,后面的代码将永远无法执行,属于“死代码”(dead code)。
示例:
public static int getNum() {return 10;System.out.println("这行永远不会执行"); // 错误!int x = 20; // 错误!
}
建议:IDE 通常会高亮提示此类无效代码,应删除或重构。
4.6 总结:方法编程五大原则
| 原则 | 说明 |
|---|---|
| 🚫 不调用不执行 | 方法定义 ≠ 执行,必须显式调用 |
| 🔁 平级关系 | 方法不能嵌套定义,全部并列于类中 |
| 🔄 顺序无关 | 定义位置不影响调用,但建议按逻辑分组 |
| 📦 void 可省 return | void 方法允许省略 return,但不可返回值 |
| ⛔ return 后无代码 | return 后的语句无效,需避免冗余 |
4. 方法的重载
在实际开发中,我们常常需要对相同功能但输入不同的场景编写多个方法。为了提高代码的可读性和复用性,Java 提供了 方法重载(Method Overloading) 的机制。
4.1 什么是方法重载?
方法重载:在同一个类中,定义多个方法名相同,但参数列表不同的方法。
- 参数列表不同包括:
- 参数个数不同;
- 参数类型不同;
- 参数顺序不同(虽合法,但不推荐);
❌ 注意:返回值类型不能作为重载的依据!
4.2 重载的判断标准(三要素)
| 判断条件 | 是否构成重载 |
|---|---|
| 方法名相同 | ✅ 必须相同 |
| 参数个数不同 | ✅ 可以重载 |
| 参数类型不同 | ✅ 可以重载 |
| 参数顺序不同 | ✅ 技术上可以,但不建议使用 |
| 返回值类型不同 | ❌ 不能构成重载 |
✅ 示例 1:参数个数不同 → 构成重载
public static int sum(int a, int b) {return a + b;
}public static int sum(int a, int b, int c) {return a + b + c;
}
✅ 示例 2:参数类型不同 → 构成重载
public static int sum(int a) {System.out.println(a);
}public static int sum(String a) {System.out.println(a);
}
✅ 示例 3:参数顺序不同 → 构成重载
public static void fn(int a, double b) {System.out.println("int + double");
}public static void fn(double a, int b) {System.out.println("double + int");
}
⚠️ 警告:虽然
fn(int, double)和fn(double, int)是合法的重载,但由于参数顺序易混淆,容易导致调用错误,因此不建议使用。
4.3 Java 如何区分同名方法?
当调用一个重载方法时,JVM 会根据实参的类型和个数来匹配最合适的版本。
示例:自动选择正确的方法
public class MethodDemo {public static int sum(int a, int b) {return a + b;}public static int sum(int a, int b, int c) {return a + b + c;}public static void main(String[] args) {System.out.println(sum(10, 20)); // 调用两个参数的版本System.out.println(sum(10, 20, 30)); // 调用三个参数的版本}
}
运行结果:
原理:
JVM 在编译期通过“方法签名”(方法名 + 参数列表)进行精确匹配,确保调用的是正确的实现。
4.4 重载的典型应用场景
- 同一功能,多种输入方式
- 比如计算面积:
area(int)、area(double)、area(int, int);
- 比如计算面积:
- 简化接口设计
- 提供多个入口,方便用户传入不同类型的数据;
- 提升代码灵活性
- 不需要为每种情况写新名字,保持命名一致性。
实际例子:
System.out.println()就是重载的经典代表!它有多个版本:
println(int)
println(double)
println(String)
println(boolean)
...
4.5 重载 vs 重写(重要区分)
| 对比项 | 方法重载 | 方法重写(Override) |
|---|---|---|
| 所在类 | 同一个类 | 子类与父类 |
| 方法名 | 相同 | 相同 |
| 参数列表 | 不同 | 必须相同 |
| 返回值 | 可不同 | 可更具体(协变) |
| 访问权限 | 无要求 | 不能缩小 |
| 关键字 | 无 | @Override(可选) |
总结:
重载是“同名不同参”,用于扩展功能;重写是“子类改父类”,用于多态。
5.方法的内存分析
5.1 方法调用的基本内存原理
程序启动,main → eat → study 依次入栈(初始调用链)

程序启动后,
main方法首先被加载进栈内存。随后执行eat()调用,eat方法进入栈中;接着在eat()内部调用study(),study方法也被压入栈顶。此时栈内存中形成了三层嵌套结构:main → eat → study。控制权当前位于study()方法内部,输出“学习”
study() 执行完毕,study 栈帧出栈,控制权返回 eat()

study()方法已执行结束,其对应的栈帧从栈顶弹出。当前栈中仅剩main和eat两个栈帧,控制权回到eat()方法中study()调用之后的位置,准备继续执行后续语句(如输出“吃饭”)
eat() 继续执行,调用 sleep(),sleep 入栈


在
eat()方法内部,study()已经执行完毕并出栈,当前执行流继续向下,先输出 “吃饭”,然后到达对sleep()的调用。此时,JVM 为sleep()创建新的栈帧,并将其压入栈顶。现在,栈内存中的方法调用顺序从底到顶依次是:main → eat → sleep。控制权转移至sleep()方法,输出“睡觉”。
eat() 执行完毕,eat 栈帧出栈,栈中仅剩 main


sleep()执行结束后出栈,eat()继续执行并完成了全部逻辑,随后eat的栈帧也被弹出。当前栈内存中仅保留main方法的栈帧,控制权回到main中eat()调用之后的位置,准备结束程序。
程序执行完毕,所有方法出栈,栈内存为空

main()方法中eat()调用已全部执行完毕,eat()、study()和sleep()的栈帧均已弹出。此时栈内存为空,表示整个程序运行结束。
5.2 基本数据类型 与 引用数据类型
5.2.1 基本数据类型


5.2.1.1 内存分析



5.2.2 引用数据类型


5.3.1.1 内存分析




