Java 进阶之路(六):构建清晰、可复用的代码

74 阅读8分钟

好的,这是一篇根据你提供的讲义内容整理的博客文章,并添加了图标和去除了一些AI化的痕迹:

Java 进阶之路(六):构建清晰、可复用的代码 🧱

在 Java 编程中,“方法”(Method)是一个至关重要的概念。它就像是程序的“积木”,可以将一段特定的逻辑功能封装起来,方便我们重复使用和管理代码。今天,我们就来深入了解 Java 方法的定义、调用、return 语句、重载以及一些实用的案例。

📦 方法:封装业务逻辑的容器

  • 函数、过程:在不同的编程语言中,方法可能被称为函数或过程,它们的核心作用是一样的:封装一段特定的业务逻辑功能
  • 保持独立:一个好的方法应该尽可能地独立,只负责完成一件事情
  • 反复调用:方法可以被反复多次调用,避免重复编写相同的代码。
  • 代码维护:使用方法可以减少代码重复,有利于代码维护,当我们修改某个功能时,只需要修改对应的方法即可。
  • 何时使用:只要是一个独立的业务功能,就应该考虑封装到一个方法中

📝 方法的定义:构成方法的五要素

定义一个 Java 方法需要包含五个要素:

修饰词 返回值类型 方法名(参数列表) {
    方法体 // 具体的业务逻辑功能实现
}

让我们通过一些例子来理解:

  • 无参无返回值

    public static void say(){
        System.out.println("大家好,我叫张三,今年38岁了");
    }
    
  • 有参无返回值

    public static void sayHi(String name){ // name 是形参(形式参数)
        System.out.println("大家好,我叫"+name+",今年38岁了");
    }
    
    public static void sayHello(String name,int age){ // name, age 是形参
        if(age>=60){ // 在某种特定条件下,提前结束方法
            return; // 结束方法
        }
        System.out.println("大家好,我叫"+name+",今年"+age+"岁了");
    }
    
  • 有参有返回值

    public static int sum(int num1,int num2){
        int num = num1+num2;
        return num; // 返回的是 num 里面的那个数
        // return num1+num2; // 直接返回 num1 与 num2 的和
    }
    
    // 生成一个整型数组,并填充随机数据
    public static int[] generateArray(int len,int max){
        Random rand = new Random();
        int[] arr = new int[len]; // 注意这里修正了 len 变量名
        for(int i=0;i<arr.length;i++){
            arr[i] = rand.nextInt(max+1); // 包括 max
        }
        return arr;
    }
    

📞 方法的调用:如何使用方法

调用方法根据是否有返回值分为两种情况:

  • 无返回值:直接通过方法名调用,如果方法有参数,需要传入实际参数。

    public static void main(String[] args) {
        say(); // 调用 say() 方法
    
        // sayHi(); // 编译错误,有参则必须传参
        // sayHi(250); // 编译错误,参数类型必须匹配
        sayHi("zhangsan"); // "zhangsan" 是实参(实际参数)
        sayHi("lisi"); // "lisi" 是实参
        System.out.println("-------------------------------");
    
        sayHello("zhangsan",25); // 25, 25 是实参
        sayHello("lisi",27); // 27, 27 是实参
    }
    
    • 形参:形式参数,定义方法时声明的参数。
    • 实参:实际参数,调用方法时传入的参数。
  • 有返回值:将方法调用的结果赋给一个变量。

    public static void main(String[] args) {
        int a = sum(5,6); // sum(5,6) 的值就是 return 后的那个数
        System.out.println(a); // 11 --- 模拟对返回值的后续操作
        int m=5,n=6;
        int b = sum(m,n); // 传的是 m 和 n 里面的数
        System.out.println(b); // 11 --- 模拟对返回值的后续操作
        System.out.println("---------------------------");
    
        int[] c = generateArray(5,10); // 模拟第1个人的访问
        System.out.println("数组的长度:"+c.length); // --- 模拟对返回值的后续操作
        for(int i=0;i<c.length;i++){ // --- 模拟对返回值的后续操作
            System.out.println(c[i]);
        }
        System.out.println("---------------------------");
    
        int[] d = generateArray(10,30); // 模拟第2个人的访问
        System.out.println("第1个元素的值:"+d[0]); // --- 模拟对返回值的后续操作
        for(int i=0;i<d.length;i++){ // --- 模拟对返回值的后续操作
            System.out.println(d[i]);
        }
    }
    

↩️ return:方法的“出口”

return 语句用于结束方法的执行,并可以选择性地返回一个值。

  • return 值;

    • 结束方法的执行。
    • 将“值”返回给调用方。
    • 用在有返回值的方法中
  • return;

    • 结束方法的执行。
    • 用在无返回值的方法中

🔄 方法的重载 (Overloading):同名方法,不同参数

方法的重载允许在同一个类中定义多个同名的方法,但它们的参数列表必须不同。

  • 同一类中,方法名相同,参数列表不同。

  • 参数列表不同指的是参数的个数不同,或者参数的类型不同,或者参数的顺序不同

  • 方法的重载与返回值类型无关

  • 方法的重载与参数名称无关

  • 编译器在编译时会根据方法的签名自动绑定相应的方法。

  • 方法的签名:方法名 + 参数列表。

    package day06;
    public class MethodDemo {
        public static void main(String[] args) {
            say(); // 自动绑定无参 say()
            say("zhangsan"); // 自动绑定 String 参的 say(String name)
            say("lisi",25); // 自动绑定 String + int 参的 say(String name, int age)
            // say(3.456); // 编译错误,没有 double 参的 say() 方法
        }
    
        // 无参无返回值
        public static void say(){
            System.out.println("大家好,我叫张三,今年39岁了");
        }
    
        // 有参无返回值 (重载示例 1)
        public static void say(String name){ // ----------------- 形参
            System.out.println("大家好,我叫"+name+",今年39岁了");
        }
    
        // 有参无返回值 (重载示例 2)
        public static void say(String name,int age){ // ------ 形参
            if(age>=50){ // 在某种特定条件下,提前结束方法
                return; // 结束方法的执行
            }
            System.out.println("大家好,我叫"+name+",今年"+age+"岁了");
        }
    
        public static void say(int age) {} // 正确的重载 (参数类型不同)
        public static void say(int age,String name){} // 正确的重载 (参数顺序不同)
        // public static int say(){ return 1; } // 编译错误,重载与返回值类型无关
        // public static void say(String address) { } // 编译错误,重载与参数名称无关
    }
    

🧩 综合案例:运用方法解决实际问题

让我们通过两个综合案例来巩固方法的应用:

  • 案例一:计算主持人比赛平均分

    package day06;
    import java.util.Scanner;
    import java.util.Random; // 导入 Random 类
    import java.util.Arrays; // 导入 Arrays 类
    
    /**
     * 需求: <<主持人大赛>>有 N 位评委给选手打分
     *     选手的最终得分为: 去掉最高分和最低分之后的 N-2 位评委的平均分
     * 要求: 使用方法实现
     */
    public class CalTotalAvg {
        public static void main(String[] args) { // 撒贝宁
            double[] scores = inputData(6); // 1) 录入评委的评分
            double avg = calAvg(scores); // 2) 计算平均分
            System.out.println("平均分为:" + avg);
        }
    
        /**
         * 该方法用于录入 N 位评委的评分
         * @param n 评委人数
         * @return 包含评委评分的数组
         */
        public static double[] inputData(int n){
            double[] scores = new double[n]; // 评分数组
            Scanner scan = new Scanner(System.in);
            for(int i=0;i<scores.length;i++){
                System.out.println("请录入第"+(i+1)+"位评委的分数:");
                scores[i] = scan.nextDouble();
            }
            return scores;
        }
    
        /**
         * 该方法用于计算平均分 (去掉最高分和最低分)
         * @param scores 包含评委评分的数组
         * @return 平均分
         */
        public static double calAvg(double[] scores){
            double total = 0.0; // 总分
            double max = scores[0]; // 假设第1个元素为最高分
            double min = scores[0]; // 假设第1个元素为最低分
            for(int i=0;i<scores.length;i++){
                total += scores[i]; // 累加所有评分
                if(scores[i]>max){ // 找最高分
                    max = scores[i];
                }
                if(scores[i]<min){ // 找最低分
                    min = scores[i];
                }
            }
            // 计算平均分 --- 总分减掉最高分和最低分之后,再除以 (评委数 - 2)
            double avg = (total-max-min)/(scores.length-2);
            return avg;
        }
    }
    
  • 案例二:猜数字小游戏

    package day06;
    import java.util.Random;
    import java.util.Scanner;
    
    /**
     * 需求: 猜数字小游戏
     * 训练目标: while(true) 自造死循环 + break
     */
    public class Guessing {
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            Random rand = new Random();
            int num = rand.nextInt(1000)+1; // 1 到 1000
            System.out.println("作弊: " + num); // 作弊,实际游戏中应删除此行
    
            while(true){ // 自造死循环
                System.out.println("猜吧!");
                int guess = scan.nextInt();
                if(guess > num){
                    System.out.println("猜大了");
                }else if(guess < num){
                    System.out.println("猜小了");
                }else{
                    System.out.println("恭喜你猜对了!");
                    break; // 跳出循环
                }
            }
        }
    }
    

🔍 Debug 调试工具:程序的“放大镜”

在编程过程中,难免会遇到错误(Bug)。学会使用调试工具(Debugger)能极大地提高我们查找和修复问题的效率。

  • 🐞 添加断点:在你想要程序暂停执行的那行代码前点击,会出现一个红点,这就是断点。
  • ▶️ Debug 运行程序:选择 Debug 方式运行程序,程序会在第一个断点处自动暂停。
  • 🚶 逐步调试
    • F7:逐语句调试,会进入到调用的方法内部。
    • F8:逐过程调试,不会进入到方法内部,直接执行完方法并跳到下一行。
    • F9:直接跳到下一个断点处,如果后面没有断点了,则调试结束。

总结

  • 方法:封装一段特定的业务逻辑功能、尽可能独立,一个方法只干一件事
  • 方法的定义:五要素
    • 修饰词返回值类型方法名(参数列表儿方法体}
  • 方法的调用:
    • 无返回值:方法名(有参传参):
    • 有返回值:数据类型变量=方法名(有参传参)
  • 方法的重载:
    • 发生在同一类中,方法名相同,参数列表不同
    • 编译器绵译时会根据方法的签名自动绑定调用方法

小结

  1. 方法的应用场景有哪些
  2. 方法的设计规则有哪些
  3. 方法重载的应用场景有哪些