欢迎光临
我们一直在努力

【第三章】Java中的输入输出、方法、数组

上一章,我们为大家介绍了Java中的数据类型,运算符的相关知识。那么本章我们就深入介绍。在上一节的基础上拓展至这一章中的方法、数组的内容。


Java基础入门系列:输入输出、方法、数组与调试全攻略

写在前面:本文整合了Java入门阶段四个核心知识点——输入输出、方法的使用、数组的定义与使用、以及IDEA调试技巧,适合Java初学者系统学习,也适合作为期末复习资料。建议收藏后配合动手实践,效果更佳!


📑 目录

  • 一、Java输入输出
  • 二、方法的使用
  • 三、数组的定义与使用
  • 四、IDEA调试案例讲解
  • 五、总结

一、Java输入输出

1.1 本节目标

  • 熟练使用Java当中的输入方法
  • 熟练使用Java当中的输出方法
  • 熟悉Java的多组输入

  • 1.2 输出到控制台

    基本语法

    System.out.println(msg); // 输出一个字符串, 带换行
    System.out.print(msg); // 输出一个字符串, 不带换行
    System.out.printf(format, msg); // 格式化输出

    注意:

    • println 输出的内容自带 \\n,print 不带 \\n
    • printf 的格式化输出方式和C语言的 printf 是基本一致的
    代码示例

    System.out.println("hello world");
    int x = 10;
    System.out.printf("x = %d\\n", x);

    格式化字符串参考

    常用的格式化占位符:

    转换符类型举例
    %d 十进制整数 printf("%d", 100)
    %f 浮点数 printf("%f", 3.14)
    %s 字符串 printf("%s", "hello")
    %c 单个字符 printf("%c", 'A')
    %b 布尔值 printf("%b", true)

    1.3 从键盘输入

    使用 Scanner 读取字符串/整数/浮点数,使用时需要导入该类(该过程为导包):

    import java.util.Scanner; // 需要导入 util 包

    Scanner sc = new Scanner(System.in);

    System.out.println("请输入你的姓名:");
    String name = sc.nextLine();

    System.out.println("请输入你的年龄:");
    int age = sc.nextInt();

    System.out.println("请输入你的工资:");
    float salary = sc.nextFloat();

    System.out.println("你的信息如下:");
    System.out.println("姓名: " + name + "\\n" + "年龄:" + age + "\\n" + "工资:" + salary);

    sc.close(); // 注意, 要记得调用关闭方法

    执行结果:

    请输入你的姓名:
    张三
    请输入你的年龄:
    18
    请输入你的工资:
    1000.0
    你的信息如下:
    姓名: 张三
    年龄:18
    工资:1000.0

    思考:如果先输入年龄、再输入姓名、再输入工资,程序会发生什么问题?

    编译器会把换行当做姓名读进去,导致姓名无法正确匹配。这时再写一个Nextline即可正确换行。


    1.4 如何处理多组输入?

    使用 Scanner 循环读取 N 个数字,并求取其平均值:

    Scanner sc = new Scanner(System.in);
    int sum = 0;
    int num = 0;

    while (sc.hasNextInt()) {
    int tmp = sc.nextInt();
    sum += tmp;
    num++;
    }

    System.out.println("sum = " + sum);
    System.out.println("avg = " + sum / num);
    sc.close();

    注意:当循环输入多个数据时,使用 Ctrl + Z(Windows CMD)或 Ctrl + D(Linux/Mac/IDEA控制台)来结束输入。


    1.5 实战:猜数字游戏

    游戏规则:系统自动生成一个随机整数(1-100),然后由用户输入一个猜测的数字。如果输入的数字比随机数小,提示"低了",如果输入的数字比随机数大,提示"高了",如果相等则提示"猜对了"。

    import java.util.Random;
    import java.util.Scanner;

    class Test {
    public static void main(String[] args) {
    Random random = new Random();
    Scanner sc = new Scanner(System.in);
    int toGuess = random.nextInt(100);

    while (true) {
    System.out.println("请输入要输入的数字: (1-100)");
    int num = sc.nextInt();
    if (num < toGuess) {
    System.out.println("低了");
    } else if (num > toGuess) {
    System.out.println("高了");
    } else {
    System.out.println("猜对了");
    break;
    }
    }
    sc.close();
    }
    }


    二、方法的使用

    2.1 本节目标

  • 掌握方法的定义以及使用
  • 掌握方法传参
  • 掌握方法重载
  • 掌握递归

  • 2.2 方法的通俗理解

    想象一下你在家里制作咖啡。你有一个"制作咖啡"的过程,这个过程其实就可以看作一个方法:

  • 准备材料:咖啡豆、水、糖、牛奶
  • 磨咖啡豆:将咖啡豆磨成粉
  • 煮水:将水煮沸
  • 冲泡:将热水倒入咖啡粉中,浸泡几分钟
  • 添加配料:根据个人喜好添加糖或牛奶
  • 享用:最后倒入杯中,享用美味的咖啡
  • 接受食材(参数),执行一系列步骤(代码),最后得到一杯咖啡(返回值)


    2.3 什么是方法(method)

    方法就是一个代码片段,类似于C语言中的"函数"。方法存在的意义:

  • 能够模块化的组织代码(当代码规模比较复杂的时候)
  • 做到代码被重复使用,一份代码可以在多个位置使用
  • 让代码更好理解更简单
  • 直接调用现有方法开发,不必重复造轮子

  • 2.4 方法定义

    // 方法定义
    修饰符 返回值类型 方法名称([参数类型 形参 ...]){
    方法体代码;
    [return 返回值];
    }

    示例一:实现一个函数,检测一个年份是否为闰年

    public class Method {
    // 方法定义
    public static boolean isLeapYear(int year) {
    if ((0 == year % 4 && 0 != year % 100) || 0 == year % 400) {
    return true;
    } else {
    return false;
    }
    }
    }

    示例二:实现一个两个整数相加的方法

    public class Method {
    // 方法的定义
    public static int add(int x, int y) {
    return x + y;
    }
    }

    【注意事项】

    序号注意点说明
    1 修饰符 现阶段直接使用 public static 固定搭配
    2 返回值类型 如果有返回值必须与返回实体类型一致,没有必须写 void
    3 方法名字 采用小驼峰命名
    4 参数列表 无参数则()为空,有参数需指定类型,多个参数用逗号隔开
    5 方法体 方法内部要执行的语句
    6 在Java中,方法必须写在类当中
    7 在Java中,方法不能嵌套定义
    8 在Java中,没有方法声明一说

    2.5 方法的调用

    问题:方法写好之后,就可以直接运行吗?

    方法的执行需要被调用,调用方式:

    public class Method {
    // 方法的定义
    public static int add(int x, int y) {
    return x + y;
    }

    public static void main(String[] args) {
    // 调用方法
    int ret = add(1, 2);
    System.out.println("ret = " + ret);

    int ret2 = add(3, 4);
    System.out.println("ret2 = " + ret2);
    }
    }

    总结:

  • 定义方法的时候,不会执行方法的代码。只有调用的时候才会执行
  • 调用方法的时候,需要使用 方法名 + 参数列表 的形式进行调用
  • 如果方法有返回值,需要接收返回值结果

  • 2.6 实参和形参的关系

    方法的形参相当于数学函数中的自变量。在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体。

    注意:实参传值给形参,必须做到类型匹配、顺序匹配、个数匹配

    经典案例:交换实参的值

    public class TestMethod {
    public static void main(String[] args) {
    int a = 10;
    int b = 20;
    System.out.println("交换前: a = " + a + " b = " + b);
    swap(a, b);
    System.out.println("交换后: a = " + a + " b = " + b);
    }

    public static void swap(int x, int y) {
    int tmp = x;
    x = y;
    y = tmp;
    }
    }

    // 运行结果
    交换前: a = 10 b = 20
    交换后: a = 10 b = 20

    原因分析:实参 a 和 b 是 main 方法中的变量,空间在 main 方法的栈中;形参 x 和 y 是 swap 方法中的变量,两者空间独立。在 swap 调用时,只是将实参的值拷贝了一份传给形参,因此对形参的操作不会影响实参。


    2.7 方法重载

    为什么需要方法重载?

    当既想计算两个整数相加,又想计算两个小数相加时,会出现参数类型不匹配的问题。方法重载可以完美解决!

    public class TestMethod {
    public static void main(String[] args) {
    add(1, 2); // 调用add(int, int)
    add(1.5, 2.5); // 调用add(double, double)
    add(1.5, 2.5, 3.5); // 调用add(double, double, double)
    }

    public static int add(int x, int y) {
    return x + y;
    }

    public static double add(double x, double y) {
    return x + y;
    }

    public static double add(double x, double y, double z) {
    return x + y + z;
    }
    }

    重载的规则:

  • 方法名必须相同
  • 参数列表必须不同(个数不同 / 类型不同 / 类型次序不同)
  • 与返回值类型是否相同无关(仅返回值不同不能构成重载)
  • 编译器在编译代码时,会对实参类型进行推演,根据推演结果来确定调用哪个方法。

    方法签名

    方法签名即经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名 + 参数列表,构成方法完整的名字。


    2.8 递归

    生活中的故事

    从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,讲的就是: “从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事…” (自身中又包含了自身)

    递归的概念

    一个方法在执行过程中调用自身,就称为"递归"。递归相当于数学上的"数学归纳法",有一个起始条件,然后有一个递推公式。

    例如,我们求 N!:

    • 起始条件:N = 1 的时候,N! 为 1(递归的结束条件)
    • 递归公式:N! => N * (N-1)!
    代码示例:递归求 N 的阶乘

    public static void main(String[] args) {
    int n = 5;
    int ret = factor(n);
    System.out.println("ret = " + ret);
    }

    public static int factor(int n) {
    if (n == 1) {
    return 1;
    }
    return n * factor(n – 1); // factor 调用函数自身
    }

    // 执行结果
    ret = 120

    更多递归练习

    1. 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

    public static void print(int num) {
    if (num > 9) {
    print(num / 10);
    }
    System.out.println(num % 10);
    }

    2. 递归求 1 + 2 + 3 + … + 10

    public static int sum(int num) {
    if (num == 1) {
    return 1;
    }
    return num + sum(num – 1);
    }

    3. 求斐波那契数列的第 N 项

    public static int fib(int n) {
    if (n == 1 || n == 2) {
    return 1;
    }
    return fib(n – 1) + fib(n – 2);
    }

    注意:当求 fib(40) 时会发现程序执行速度极慢,原因是进行了大量的重复运算。在实际开发中,递归虽然代码简洁,但要注意性能问题。


    三、数组的定义与使用

    3.1 本节目标

  • 理解数组基本概念
  • 掌握数组的基本用法
  • 数组与方法互操作
  • 熟练掌握数组相关的常见问题和代码

  • 3.2 为什么使用数组?

    假设要存5个学生的考试成绩并输出:

    public class TestStudent {
    public static void main(String[] args) {
    int score1 = 70;
    int score2 = 80;
    int score3 = 85;
    int score4 = 60;
    int score5 = 90;
    // … 逐个输出
    }
    }

    如果有100个学生呢?创建100个变量?数组就是用来解决这个问题的!


    3.3 什么是数组?

    数组:可以看成是相同类型元素的一个集合,在内存中是一段连续的空间。

    关键特点:

  • 数组的空间是连在一起的
  • 每个空间有自己的编号,起始位置的编号为0,即数组的下标

  • 3.4 数组的创建及初始化

    数组的创建

    T[] 数组名 = new T[N];

    • T:表示数组中存放元素的类型
    • T[]:表示数组的类型
    • N:表示数组的长度

    int[] array1 = new int[10]; // 容纳10个int类型元素的数组
    double[] array2 = new double[5]; // 容纳5个double类型元素的数组
    String[] array3 = new String[3]; // 容纳3个字符串元素的数组

    数组的初始化

    1. 动态初始化:在创建数组时,直接指定数组中元素的个数

    int[] array = new int[10];

    2. 静态初始化:在创建数组时直接指定具体的数据内容

    int[] array1 = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};
    String[] array3 = new String[]{"hello", "Java", "!!!"};

    静态初始化可以简写:

    int[] array1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    double[] array2 = {1.0, 2.0, 3.0, 4.0, 5.0};
    String[] array3 = {"hello", "Java", "!!!"};

    【注意事项】

    • 静态初始化虽然没有指定数组长度,编译器在编译时会根据 {} 中元素个数确定
    • 静态初始化时,{} 中数据类型必须与 [] 前数据类型一致
    • 省略格式不可以拆分,只能在定义的同时初始化

    3.5 数组的基本使用

    数组中元素访问

    int[] array = new int[]{10, 20, 30, 40, 50};
    System.out.println(array[0]); // 10
    System.out.println(array[1]); // 20

    // 通过[]修改元素
    array[0] = 100;
    System.out.println(array[0]); // 100

    注意:下标从0开始,范围是 [0, N),不能越界,否则会抛出 ArrayIndexOutOfBoundsException

    遍历数组

    方式一:普通for循环

    int[] array = new int[]{10, 20, 30, 40, 50};
    for (int i = 0; i < array.length; i++) {
    System.out.println(array[i]);
    }

    在数组中可以通过 数组对象.length 来获取数组的长度

    方式二:for-each 遍历

    int[] array = {1, 2, 3};
    for (int x : array) {
    System.out.println(x);
    }

    for-each 是 for 循环的另一种使用方式,能更方便地完成对数组的遍历,可以避免循环条件和更新语句写错。


    3.6 数组是引用类型

    JVM内存分布

    JVM对所使用的内存按功能进行了划分:

    区域作用
    程序计数器 (PC Register) 保存下一条执行指令的地址
    虚拟机栈 (JVM Stack) 与方法调用相关的信息,每个方法执行时会创建栈帧
    本地方法栈 (Native Method Stack) 保存Native方法的局部变量
    堆 (Heap) JVM管理的最大内存区域,new 创建的对象都在堆上
    方法区 (Method Area) 存储类信息、常量、静态变量等
    基本类型 vs 引用类型
    • 基本数据类型:变量空间中直接存放的是其对应的值
    • 引用数据类型:变量空间中存储的是对象所在空间的地址

    public static void func() {
    int a = 10; // a空间中存的就是10
    int b = 20; // b空间中存的就是20
    int[] arr = new int[]{1, 2, 3}; // arr存的是数组在堆中的地址
    }

    认识 null

    null 在Java中表示"空引用",也就是一个不指向对象的引用。

    int[] arr = null;
    System.out.println(arr[0]); // 抛出 NullPointerException

    null 的作用类似于C语言中的 NULL(空指针),表示一个无效的内存位置,因此不能对其进行任何读写操作。


    3.7 数组的应用场景

    数组作为函数的参数

    public static void main(String[] args) {
    int[] arr = {1, 2, 3};
    func(arr);
    System.out.println("arr[0] = " + arr[0]); // arr[0] = 10
    }

    public static void func(int[] a) {
    a[0] = 10;
    System.out.println("a[0] = " + a[0]); // a[0] = 10
    }

    数组是引用类型,传参时传递的是地址,因此在方法内部修改数组内容,外部的数组也会改变。

    数组作为函数的返回值

    获取斐波那契数列的前N项:

    public static int[] fib(int n) {
    if (n <= 0) {
    return null;
    }
    int[] array = new int[n];
    array[0] = array[1] = 1;
    for (int i = 2; i < n; ++i) {
    array[i] = array[i – 1] + array[i – 2];
    }
    return array;
    }


    3.8 操作数组工具类 Arrays

    数组转字符串

    import java.util.Arrays;

    int[] arr = {1, 2, 3, 4, 5, 6};
    String newArr = Arrays.toString(arr);
    System.out.println(newArr); // [1, 2, 3, 4, 5, 6]

    数组拷贝

    int[] arr = {1, 2, 3, 4, 5, 6};
    int[] newArr = Arrays.copyOf(arr, arr.length); // 完整拷贝
    int[] newArr2 = Arrays.copyOfRange(arr, 2, 4); // 拷贝[2,4)范围

    二分查找

    针对有序数组,可以使用更高效的二分查找:

    public static int binarySearch(int[] arr, int toFind) {
    int left = 0;
    int right = arr.length – 1;
    while (left <= right) {
    int mid = (left + right) / 2;
    if (toFind < arr[mid]) {
    right = mid – 1; // 去左侧区间找
    } else if (toFind > arr[mid]) {
    left = mid + 1; // 去右侧区间找
    } else {
    return mid; // 找到了
    }
    }
    return –1; // 没找到
    }

    冒泡排序

    public static void bubbleSort(int[] arr) {
    for (int i = 0; i < arr.length; i++) {
    for (int j = 1; j < arr.length – i; j++) {
    if (arr[j – 1] > arr[j]) {
    int tmp = arr[j – 1];
    arr[j – 1] = arr[j];
    arr[j] = tmp;
    }
    }
    }
    }

    Java 内置了更高效的排序:Arrays.sort(arr);

    数组逆序

    public static void reverse(int[] arr) {
    int left = 0;
    int right = arr.length – 1;
    while (left < right) {
    int tmp = arr[left];
    arr[left] = arr[right];
    arr[right] = tmp;
    left++;
    right—;
    }
    }


    3.9 二维数组

    二维数组本质上也就是一维数组,只不过每个元素又是一个一维数组。

    int[][] arr = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
    };

    for (int row = 0; row < arr.length; row++) {
    for (int col = 0; col < arr[row].length; col++) {
    System.out.printf("%d\\t", arr[row][col]);
    }
    System.out.println("");
    }

    • arr.length 代表二维数组的行数
    • arr[row].length 代表二维数组的列数

    不规则的二维数组:

    int[][] array = new int[2][];
    array[0] = new int[3]; // 第1行有3列
    array[1] = new int[5]; // 第2行有5列


    四、IDEA调试案例讲解

    4.1 什么是调试?

    当我们发现程序中存在的问题时,去查找和改正错误的过程称为调试(debugging)。

    调试的一般途径是采用各种方法逐步缩小 bug 所在的范围,最终定位 bug 的准确位置。


    4.2 常见的调试方式

    方式适用场景具体做法
    阅读代码跟踪 代码量短小 逐行阅读代码 + 插入打印语句观察
    使用工具 复杂程序 使用集成开发工具中集成的调试器

    4.3 使用IDEA调试Java程序

    打断点

    点击鼠标左键,出现红色按钮即打断点成功。

    启动调试

    鼠标右键,点击 Debug… 即可启动调试模式。


    4.4 IDEA调试核心功能速查表

    功能快捷键说明
    逐过程 (Step Over) F8 逐行执行,不进入方法内部
    逐语句 (Step Into) F7 进入方法内部执行
    强制步入 (Force Step Into) Alt + Shift + F7 强制进入任何方法(包括库方法)
    跳出 (Step Out) Shift + F8 跳出当前方法,返回调用位置
    运行到光标处 Alt + F9 程序跳转到光标所在行
    重新调试 Ctrl + F5 重新开始调试
    暂停调试 Ctrl + F2 停止当前调试
    显示所有断点 Ctrl + Shift + F8 集中管理所有断点

    普通 Step Into vs Force Step Into:普通F7通常会跳过库方法、无源代码的方法等,而Force Step Into会进入任何方法。


    4.5 调试界面重要功能

    Debugger标签

    展示调用堆栈以及变量等表达式的值。例如 add:13, main:9 属于调用堆栈信息,先调用 main 方法,后调用 add 方法。

    在 Evaluate expression 输入框中可以输入表达式进行求值或添加到监视列表。

    Console标签

    展示控制台的输入输出信息,遇到输出语句时可以查看输出结果。

    条件断点

    当一个代码需要满足某种条件才进行调试时:

  • 打断点
  • 鼠标右键,添加条件
  • 开始调试,程序会停在满足条件的位置

  • 五、总结

    本文从Java基础入门的四个核心模块出发,系统梳理了:

    模块核心内容
    输入输出 println/print/printf输出、Scanner输入、多组输入处理、猜数字实战
    方法 方法定义与调用、传参机制、方法重载、递归思想与实践
    数组 数组创建与初始化、遍历方式、引用类型原理、Arrays工具类、二分查找、排序算法、二维数组
    IDEA调试 断点设置、Step Over/Into/Out、条件断点、变量监视

    学习建议:理论结合实践,多敲代码多Debug,才能真正掌握这些基础知识点。遇到问题时善用IDEA的调试功能,事半功倍!


    那么本章就到此结束了。本章为大家展示了输入输出,方法,数组和IDEA中的一些调试方法

    赞(0)
    未经允许不得转载:171主机测评 » 【第三章】Java中的输入输出、方法、数组
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址