☕ 第二章 Java编程基础

2.6 方法

📄 一句话概括

方法 = 会做事的积木:把一段代码起个名字打包,以后喊名字就执行。数据从参数进门,结果从 return 出门——写一次,到处喊。

前置知识:2.2 Java中的变量(形参就是普通变量格子)、2.5 循环结构语句(方法里经常装循环)。

其实你早就在喊方法了:System.out.println(...) 就是喊别人写好的 println 方法干活——本节只是学着自己写一个。


1. 为什么需要方法

不用方法,"算两个数的和"要用三次就得复制粘贴三遍;改需求(比如改成求乘积)要改三处,漏一处就出 bug。方法把这段代码打包成积木:定义一次,哪里要算就喊一次——复用是它唯一的追求。

2. 方法的定义:五个部位

public static int add(int a, int b) {
    int sum = a + b;
    return sum;
}
部位 例子 作用
修饰符 public static 先照抄,第五章面向对象再解释它
返回值类型 int 这个方法干完活,交回来的结果是什么类型
方法名 add 喊它用的名字,小驼峰,见名知义
参数列表 int a, int b 干活需要的原料,几个格子、什么类型
方法体 { ... return sum; } 真正干活的代码
💡 两个"必须配对"
  1. 返回值类型 ↔ return 的东西:声明返回 int,就必须 return 一个 int 值——说好交整数就得交整数
  2. 参数列表 ↔ 调用时传的实参:定义收两个 int,调用就必须给两个 int——add(3) 或 add(3, 5.0) 都直接报错

3. 调用:喊积木干活

public class Demo07 {
    public static void main(String[] args) {
        int result = add(3, 5);       // 喊 add,把 3 和 5 送进去,接住回来的 8
        System.out.println(result);   // 8
        System.out.println(add(10, 20));   // 也可以直接喊,不用接
    }

    public static int add(int a, int b) {
        return a + b;
    }
}

调用时发生的四件事(对应上面的图):

  1. add(3, 5) —— 喊名字,递原料(实参:3 和 5)
  2. 3 住进 a,5 住进 b(形参:a、b 就是方法自己的格子)——注意是"复制值进去",方法里改 a 不影响外面的 3
  3. 执行方法体,算出 8
  4. return 把 8 送回调用处,装进 result——程序回到原地接着走
📝 形参 vs 实参,一张嘴记住

形参是定义时的"占位格子"(int a, int b)——形式上的参数,得等人来住;实参是调用时"真送来的值"(3, 5)——实际的参数。对号入座:第 1 个实参住第 1 个形参,数量、类型都得配。

4. 三种常见形态

// ① 无参有返回:不要原料,交结果
public static int getTen() {
    return 10;
}

// ② 有参无返回(void):给原料,只干活不回报
public static void printLine(int n) {
    for (int i = 0; i < n; i++) {
        System.out.print("-");
    }
    System.out.println();      // 打完一行换行,不需要 return 什么
}

// ③ 有参有返回:最常用
public static double circleArea(double r) {
    return 3.14159 * r * r;
}

调用区别:

int x = getTen();          // 有返回值 → 可以接住
printLine(20);             // void → 只能直接喊,接不了(int x = printLine(20); 报错)
double s = circleArea(2.5);// 接住 19.63...
⚠️ void 的两个规矩
  1. int result = printLine(20); 编译报错——void 不交货,没法接
  2. void 方法里可以写 return;(不带值),作用是"到此为止,提前回去",类似 2.5 里 break 的急刹效果

5. 方法的三个家规

  1. 方法必须住在类里,不能裸写在类外面——Java 一切代码都在类里(1.3 就见过的规矩)
  2. 方法之间不能嵌套定义——方法里不能再写一个方法,积木和平积木
  3. 定义顺序无所谓——main 在前 add 在后照样能调用(编译器不按行数念经),但执行永远从 main 开始:main 是总指挥,你不喊,方法自己不会动
📝 方法和变量一样有作用域

方法体里定义的变量(包括形参),出了方法的 {} 就消失。两个方法里都写 int temp 互不打架——各自的方法各自的格子。

6. 动手:Demo07 积木三连

第 1 步:IDEA02 项目 → src → New → Java Class → Demo07,psvm 生成主方法。

第 2 步:抄入(方法写在 main 的下面,同一层级):

public class Demo07 {
    public static void main(String[] args) {
        int result = add(3, 5);
        System.out.println(result);          // 8

        printLine(20);                       // 打印一行 20 个 -
        printLine(30);                       // 再喊一次,30 个 —— 复用的爽点

        System.out.println(circleArea(2.5)); // 19.624...
    }

    public static int add(int a, int b) {
        return a + b;
    }

    public static void printLine(int n) {
        for (int i = 0; i < n; i++) {
            System.out.print("-");
        }
        System.out.println();
    }

    public static double circleArea(double r) {
        return 3.14159 * r * r;
    }
}

第 3 步:绿三角 ▶ 运行,核对输出。

第 4 步(两个 30 秒实验):

  1. 把 add(3, 5) 改成 add(3)——看"参数数量不对"的报错长什么样(IDEA 红线当场就报)
  2. 把 add 里的 return a + b; 暂时删掉——看"缺少返回语句"的报错。说好交 int 就得交,亲眼见一次

7. 常见误区小结

⚠️ 误区 1:不喊不动

定义了方法但没人调用它,一个字都不会执行——执行从 main 开始,main 是总指挥。

⚠️ 误区 2:返回值类型和 return 对不上

声明 int 却 return 3.5,报错;声明 int 却漏了 return(某些分支没返回),报错。合同说了交什么就得交什么。

⚠️ 误区 3:想接住 void 的"结果"

void 不交货。要结果就把返回值类型改成对应类型并 return。

⚠️ 误区 4:以为方法里改形参会改变外面的变量

传值是复制:int x = 3; change(x); 方法里把 a 改成 100,外面的 x 还是 3。两套格子,各管各的。

⚠️ 误区 5:方法定义在类外面或方法里面

必须住在类的 {} 里、和其他方法平级——不能裸放,也不能套娃。


8. 自测题

❓ Q1:`public static int add(int a, int b)` 里,哪个是形参、哪个是实参?调用 `add(3, 5)` 时发生了什么?

定义里的 a、b 是形参(占位格子),调用时的 3、5 是实参(真送来的值)。调用时:3 住进 a、5 住进 b → 执行方法体算 a+b → return 把 8 送回调用处,程序回到原地接着走。

❓ Q2:`void printHello()` 和 `int getAge()` 分别怎么调用?能写 `int x = printHello();` 吗?

printHello(); 直接喊(不接);int x = getAge(); 接住返回值。不能写 int x = printHello();——void 不交货,编译报错。

❓ Q3:下面代码输出什么?为什么?
public static void main(String[] args) {
    int x = 3;
    change(x);
    System.out.println(x);
}
public static void change(int a) {
    a = 100;
}

输出 3。传参是复制值:x 的 3 被复制进 a 的格子,方法里改的是 a,外面的 x 毫发无损。两套格子各管各的。

❓ Q4:写一个方法 `isEven(int n)`,返回"n 是不是偶数"。想三种返回值写法,哪种最地道?

① if (n % 2 == 0) { return true; } else { return false; }(能用);② boolean flag = n % 2 == 0; return flag;(分步);③ return n % 2 == 0;(最地道——表达式本身就是 boolean,直接交出去)。体会一下"比较运算符的返回值就是 boolean"(2.3)能省多少代码。

❓ Q5:方法体里写的 `int temp` 和另一个方法里的 `int temp` 冲突吗?方法能定义在另一个方法里面吗?

不冲突——方法体里定义的变量出了方法的 {} 就消失,两个方法各有各的格子(作用域规则)。方法不能嵌套定义,积木和平积木;方法必须住在类的 {} 里、彼此平级。


9. 下一步学什么


10. 相关笔记