当前位置: 首页 > news >正文

Java循环结构全解析

java循环结构

循环结构用于重复执行一段相同或相似的代码,直到满足某个特定的条件才停止执行。它是简化代码、处理批量任务不可或缺的工具。

Java中主要的循环结构有:for 循环、while 循环 和 do...while 循环。


一、for 循环

for 循环是最常用、结构最清晰的循环,特别适用于循环次数明确的场景。

1. 基本语法与执行流程
  • 语法

    java

    for (初始化语句; 循环条件; 迭代语句) {// 循环体:要重复执行的代码
    }
    
  • 执行流程(非常重要):

    1. 执行初始化语句(只在循环开始时执行一次)。
    2. 判断循环条件
      • 如果为 true,则执行循环体。
      • 如果为 false,则循环结束。
    3. 执行循环体
    4. 执行迭代语句(通常用于改变循环变量)。
    5. 重复步骤 2、3、4,直到条件为 false
  • 示例:打印 5 次 “Hello, World!”

    java

    for (int i = 0; i < 5; i++) {System.out.println("Hello, World! - " + i);
    }
    
    • int i = 0;:初始化一个循环计数器 i,并从 0 开始。

    • i < 5;:循环条件。只要 i 小于 5,循环就继续。

    • i++:迭代语句。每次循环结束后,i 的值增加 1。

    • 输出结果

      text

      Hello, World! - 0
      Hello, World! - 1
      Hello, World! - 2
      Hello, World! - 3
      Hello, World! - 4
      
2. 特殊用法
  • 死循环:如果循环条件永远为 true,则循环会无限执行下去。

    java

    for (;;) { // 初始化、条件、迭代都可以省略,但分号不能省System.out.println("这是一个死循环");// 实际开发中,通常会用break来在某种条件下跳出这种循环
    }
    
  • 多个变量:初始化语句和迭代语句可以包含多条语句,用逗号 , 分隔。

    java

    for (int i = 0, j = 10; i < j; i++, j--) {System.out.println("i=" + i + ", j=" + j);
    }
    

二、while 循环

while 循环适用于循环次数不明确,但循环条件明确的场景。它的逻辑是:“当…时,就一直做…”。

1. 基本语法与执行流程
  • 语法

    java

    while (循环条件) {// 循环体
    }
    
  • 执行流程

    1. 判断循环条件。
    2. 如果条件为 true,则执行循环体;如果为 false,则结束循环。
    3. 执行完循环体后,再次回到步骤 1
  • 示例 1:模拟用户输入,直到输入 “quit” 为止

    java

    Scanner scanner = new Scanner(System.in);
    String input = "";
    while (!input.equals("quit")) { // 只要输入的不是"quit",循环就继续System.out.print("请输入指令:");input = scanner.nextLine();System.out.println("你输入了: " + input);
    }
    scanner.close();
    
  • 示例 2:计算 1 到 100 的和

    java

    int sum = 0;
    int num = 1;
    while (num <= 100) {sum += num;num++;
    }
    System.out.println("1-100的和是:" + sum);
    

三、do…while 循环

do...while 循环是 while 循环的变体。它先执行一次循环体,然后再判断条件。因此,循环体至少会被执行一次

1. 基本语法与执行流程
  • 语法

    java

    do {// 循环体
    } while (循环条件); // 注意这里的分号!
    
  • 执行流程

    1. 先执行一次循环体。
    2. 然后判断循环条件。
    3. 如果条件为 true,则回到步骤 1;如果为 false,则结束循环。
  • 示例:菜单选择,至少显示一次

    java

    Scanner scanner = new Scanner(System.in);
    int choice;
    do {System.out.println("----- 菜单 -----");System.out.println("1. 开始游戏");System.out.println("2. 加载存档");System.out.println("3. 退出");System.out.print("请选择:");choice = scanner.nextInt();
    } while (choice < 1 || choice > 3); // 如果输入的不是1,2,3,就循环提示System.out.println("你选择了: " + choice);
    // ... 根据choice执行后续操作
    scanner.close();
    

四、循环控制语句

循环控制语句可以改变循环的正常执行流程。

控制语句作用适用循环
break跳出循环,终止整个循环结构的执行,继续执行循环后面的代码。for, while, do...while, switch
continue跳过本次循环,立即开始下一次循环(继续执行迭代语句和条件判断)。for, while, do...while
return跳出所在的方法,循环和它后面的代码都不会再执行。任何结构
  • break 示例:在数组中查找数字,找到后立即终止循环,提高效率。

    java

    int[] numbers = {10, 20, 30, 40, 50};
    int target = 30;
    boolean found = false;for (int num : numbers) {if (num == target) {found = true;break; // 找到后立即跳出循环,不再检查后面的元素}
    }
    System.out.println("找到了吗? " + found);
    
  • continue 示例:打印 1-10 之间的所有奇数。

    java

    for (int i = 1; i <= 10; i++) {if (i % 2 == 0) { // 如果是偶数continue; // 跳过本次循环的剩余语句,直接执行i++,然后进入下一次循环}System.out.println(i);
    }
    

五、增强 for 循环 (for-each Loop)

这是 JDK 5 引入的一种简化语法,专门用于遍历数组和集合(如 ArrayList)中的所有元素。它避免了操作索引的麻烦,更简洁,不易出错。

  • 语法

    java

    for (元素类型 局部变量 : 数组或集合对象) {// 使用局部变量即可访问当前元素
    }
    
  • 示例:遍历数组和集合

    java

    // 遍历数组
    int[] numbers = {1, 2, 3, 4, 5};
    for (int num : numbers) {System.out.println(num);
    }// 遍历集合(例如ArrayList)
    ArrayList<String> list = new ArrayList<>();
    list.add("Apple");
    list.add("Banana");
    list.add("Orange");
    for (String fruit : list) {System.out.println(fruit);
    }
    
  • 注意:增强 for 循环是只读的,你不能用它来修改原数组或集合中的元素(对于基本数据类型)或重新赋值(对于引用数据类型)。


六、嵌套循环

一个循环体内又可以包含另一个完整的循环结构,称为嵌套循环。

  • 示例:打印九九乘法表

    java

    for (int i = 1; i <= 9; i++) { // 外层循环控制行for (int j = 1; j <= i; j++) { // 内层循环控制列System.out.print(j + "×" + i + "=" + (i * j) + "\t");}System.out.println(); // 换行
    }
    

七、循环结构的选择:for vs. while vs. do-while

循环类型特点适用场景
for循环次数明确。结构紧凑,初始化、条件、迭代都写在一起,一目了然。遍历数组、执行固定次数的任务(如打印10次)
while循环次数不明确,但条件明确。“当…时,就循环”。可能一次都不执行。读取文件直到末尾、等待用户输入特定指令、游戏主循环
do-while循环次数不明确,但条件明确,且循环体至少需执行一次。“先做,再看条件”。菜单显示、密码验证(至少要让用户输入一次)

一、核心概念:数据的集装箱

想象一下现实中的集装箱

  • 固定大小:一个集装箱在制造出来时,它的容量就固定了。
  • 存放同类物品:一个集装箱通常只存放一类物品,比如全是电视,或全是水果。
  • 每个位置有编号:每个集装箱位都有一个唯一的编号(如A01,B02),方便快速定位和存取货物。

Java中的一维数组就是这个概念的数字体现:

  • 固定长度:数组一旦被创建,其长度就不可改变。
  • 相同数据类型:数组中的所有元素必须是相同的数据类型(如全是 int,或全是 String)。
  • 索引访问:每个元素都有一个从 0 开始的数字索引,通过索引可以快速访问或修改任何位置的元素。

二、数组的声明与初始化

数组的使用分为三个步骤:声明、初始化、赋值/访问。

1. 声明数组

声明数组主要是告诉编译器数组的名称和它将存储的元素类型。

  • 语法

    java

    // 首选方式
    数据类型[] 数组名; // 另一种方式(来源于C/C++,Java中允许但不推荐,可读性较差)
    数据类型 数组名[];
    
  • 示例

    java

    int[] numbers; // 声明一个整型数组,名为numbers
    String[] names; // 声明一个字符串数组,名为names
    double scores[]; // 不推荐的方式
    

    注意:此时仅仅是声明了一个数组变量(引用),它还没有指向任何实际的内存空间,其值为 null。无法使用,否则会报 NullPointerException

2. 初始化数组

初始化是为数组分配内存空间的过程。Java中主要有两种初始化方式:

  • 静态初始化:在声明数组的同时,直接指定元素内容。

    java

    // 语法:数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ..., 元素n};
    // 简写语法(只能在声明时使用):数据类型[] 数组名 = {元素1, 元素2, ..., 元素n};int[] numbers = new int[]{1, 2, 3, 4, 5};
    String[] weekdays = {"Mon", "Tue", "Wed", "Thu", "Fri"}; // 简写方式
    
  • 动态初始化:在声明数组时,只指定数组的长度,系统会为每个元素分配默认值。

    java

    // 语法:数据类型[] 数组名 = new 数据类型[数组长度];int[] numbers = new int[5]; // 创建一个长度为5的int数组,默认值全是0
    boolean[] flags = new boolean[3]; // 创建一个长度为3的boolean数组,默认值全是false
    String[] names = new String[4]; // 创建一个长度为4的String数组,默认值全是null
    

    数组元素的默认值

    数据类型默认值
    byte,short,int0
    long0L
    float0.0F
    double0.0
    char'\u0000'(空字符)
    booleanfalse
    引用类型null

三、数组的访问与操作

1. 访问元素:使用索引

数组元素通过索引来访问。索引是从 0 开始,到 数组长度 - 1 结束的整数。

  • 语法数组名[索引]

  • 示例

    java

    int[] numbers = {10, 20, 30, 40};// 获取元素
    int firstElement = numbers[0]; // 获取第一个元素:10
    int thirdElement = numbers[2]; // 获取第三个元素:30// 修改元素
    numbers[1] = 200; // 将第二个元素从20改为200
    System.out.println(numbers[1]); // 输出:200
    
2. 获取数组长度

使用数组对象的 length 属性(注意:不是方法,后面没有())来获取数组的长度。

  • 语法数组名.length

  • 示例:遍历数组(这是数组最常用的操作)

    java

    int[] numbers = {10, 20, 30, 40, 50};// 使用for循环遍历
    for (int i = 0; i < numbers.length; i++) { // 条件 i < numbers.length 是关键!System.out.println("Element at index " + i + ": " + numbers[i]);
    }// 使用增强for循环(for-each)遍历(JDK5+)
    for (int num : numbers) {System.out.println("Element: " + num);
    }
    

    注意for-each 循环更简洁,但只能用于读取元素,不能用于修改原数组(对于基本类型)或获取当前元素的索引。


四、内存原理与常见异常

1. 内存模型(重要理解)

java

int[] arr;           // 栈内存中声明一个引用变量arr,值为null
arr = new int[3];    // 在堆内存中开辟一块连续空间,存放3个int,并赋默认值0。// 然后将这块内存空间的地址赋值给引用变量arr。
arr[0] = 10;         // 通过地址找到堆内存中的数组,修改第一个位置的值为10。

关键点:数组是引用数据类型。变量 arr 存储的是数组对象在堆内存中的地址,而不是数据本身。

2. 常见异常
  • 空指针异常 (NullPointerException)
    当数组变量仅为声明(null)而未初始化(new)时,尝试访问其长度或元素会抛出此异常。

    java

    int[] arr = null;
    System.out.println(arr[0]); // 运行时抛出 NullPointerException
    System.out.println(arr.length); // 运行时抛出 NullPointerException
    
  • 数组索引越界异常 (ArrayIndexOutOfBoundsException)
    当尝试访问不存在的索引(即索引 < 0 或索引 >= 数组长度)时抛出。

    java

    int[] arr = {1, 2, 3};
    System.out.println(arr[3]); // 最大有效索引是2,访问3会越界
    System.out.println(arr[-1]); // 索引为负数,越界
    

    牢记:数组的有效索引范围永远是 [0, array.length - 1]


五、数组的常用操作与案例

1. 求最值

java

int[] numbers = {12, 45, 7, 89, 3, 56};
int max = numbers[0]; // 假设第一个元素是最大值
for (int i = 1; i < numbers.length; i++) {if (numbers[i] > max) {max = numbers[i];}
}
System.out.println("最大值是: " + max);
2. 元素求和/平均值

java

int sum = 0;
for (int num : numbers) {sum += num;
}
double average = (double) sum / numbers.length;
System.out.println("总和: " + sum + ", 平均值: " + average);
3. 数组反转
java
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {// 交换首尾对称位置的元素int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}
// 反转后arr变为:{5, 4, 3, 2, 1}

二维数组本质上就是一维数组的数组。它可以将数据组织成的表格形式,非常适合表示矩阵、棋盘、地图等结构化数据。


一、核心概念:数组的数组

想象一下现实中的公寓楼Excel表格

  • 一栋公寓楼有多个楼层(),每个楼层又有多个房间()。
  • 一个Excel表格有多个行,每个行又有多个单元格(列)。

Java中的二维数组就是这个概念的数字体现:

  • 一个二维数组变量指向一个一维数组,这个一维数组中的每个元素又是一个一维数组
  • 第一个维度通常代表,第二个维度代表

二、二维数组的声明与初始化

和一维数组一样,二维数组的使用也分为声明、初始化、赋值/访问。

1. 声明二维数组

声明主要是告诉编译器数组的名称和它将存储的元素类型。

  • 语法

    java

    // 首选方式
    数据类型[][] 数组名;// 另一种方式(允许但不推荐)
    数据类型 数组名[][];
    数据类型[] 数组名[];
    
  • 示例

    java

    int[][] matrix;     // 声明一个整型的二维数组
    String[][] table;   // 声明一个字符串的二维数组
    double[][] scores;  // 声明一个双精度的二维数组
    

    注意:此时数组变量还未初始化,值为 null

2. 初始化二维数组

同样分为静态初始化和动态初始化。

  • 静态初始化:直接指定所有元素的值。

    java

    // 语法:数据类型[][] 数组名 = new 数据类型[][]{{元素...}, {元素...}, ...};
    // 简写语法:数据类型[][] 数组名 = {{元素...}, {元素...}, ...};int[][] matrix = new int[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}
    };// 简写方式(更常用)
    String[][] names = {{"Mr.", "Mrs.", "Ms."},{"Smith", "Jones", "Lee"}
    };
    
  • 动态初始化:只指定数组的大小(行数和列数),系统会为每个元素分配默认值。

    java

    // 方式一:直接指定行数和列数
    // 语法:数据类型[][] 数组名 = new 数据类型[行数][列数];
    int[][] matrix = new int[3][4]; // 创建一个3行4列的矩阵,所有元素默认值为0// 方式二:先指定行数,再分别为每一行指定列数(创建不规则数组)
    // 语法:数据类型[][] 数组名 = new 数据类型[行数][];
    char[][] pyramid = new char[5][]; // 创建一个有5行的二维数组,但每行的列数还未定pyramid[0] = new char[1]; // 第0行有1列
    pyramid[1] = new char[2]; // 第1行有2列
    pyramid[2] = new char[3]; // 第2行有3列
    pyramid[3] = new char[4]; // 第3行有4列
    pyramid[4] = new char[5]; // 第4行有5列
    // 这样就创建了一个金字塔形的"不规则数组"
    

三、二维数组的访问与操作

1. 访问元素:使用行列索引

通过两个索引来访问元素:[行索引][列索引]。两个索引都从 0 开始。

  • 示例

    java

    int[][] matrix = {{10, 20, 30},{40, 50, 60}
    };// 获取元素
    int element = matrix[0][1]; // 获取第0行第1列的元素:20
    System.out.println(element);// 修改元素
    matrix[1][2] = 600; // 将第1行第2列的元素从60改为600
    
2. 获取数组的长度

二维数组有两个重要的长度属性

  1. 数组名.length:获取行数(即外层一维数组的长度)。
  2. 数组名[行索引].length:获取指定行的列数(即内层某个一维数组的长度)。
  • 示例:遍历二维数组(使用嵌套循环)

    java

    int[][] matrix = {{1, 2, 3},{4, 5},{6, 7, 8, 9} // 这是一个不规则数组
    };// 标准for循环遍历(可以获取索引)
    for (int i = 0; i < matrix.length; i++) { // 外层循环控制行for (int j = 0; j < matrix[i].length; j++) { // 内层循环控制当前行的列System.out.print(matrix[i][j] + " ");}System.out.println(); // 换行
    }// 增强for循环(for-each)遍历(更简洁,用于只读操作)
    for (int[] row : matrix) { // 注意:每个row是一个一维数组for (int element : row) {System.out.print(element + " ");}System.out.println();
    }
    

    输出结果

    text

    1 2 3 
    4 5 
    6 7 8 9 
    

    关键点:在嵌套的标准 for 循环中,内层循环的条件必须是 j < matrix[i].length,而不是 j < matrix[0].length,这样才能正确处理不规则数组。


四、内存原理

理解二维数组的内存模型对于深入掌握Java至关重要。

java

int[][] arr = new int[2][3];
  1. 在栈内存中创建引用变量 arr
  2. new int[2][3] 在堆内存中开辟空间:
    • 首先创建一个长度为2的外层数组,其元素类型是 int[](引用类型)。每个元素的默认值是 null
    • 然后为外层数组的每个元素(即每一行)再分别创建一个长度为3的内层数组,其元素类型是 int。每个内层数组的元素默认值是 0
    • 最后将内层数组的内存地址赋给外层数组对应的元素。

不规则数组的内存分配

java

int[][] irregularArr = new int[3][]; // 只创建了外层数组,元素全是null
irregularArr[0] = new int[2]; // 为第0行创建长度为2的内层数组
irregularArr[1] = new int[3]; // 为第1行创建长度为3的内层数组
irregularArr[2] = new int[1]; // 为第2行创建长度为1的内层数组

五、常见应用案例

1. 矩阵转置

将矩阵的行列互换。

java

int[][] original = {{1, 2, 3},{4, 5, 6}
};
int rows = original.length;
int cols = original[0].length;int[][] transposed = new int[cols][rows]; // 新矩阵的行数=原矩阵列数,列数=原矩阵行数for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {transposed[j][i] = original[i][j]; // 行列索引互换}
}
// 转置后transposed为:
// { {1, 4},
//   {2, 5},
//   {3, 6} }
2. 杨辉三角(帕斯卡三角)

java

java方法

方法是Java中组织代码实现代码复用的核心机制。它也被称为函数。你可以将它理解为一种“技能”或“工具”,一旦定义好,就可以在需要时反复使用,而无需重复编写相同的代码。


一、核心概念:封装与复用

想象一下现实生活中的场景:

  • 你有一台榨汁机。你不需要每次都重新发明如何榨汁,只需要把水果放进去(输入),按下开关,它就会给你果汁(输出)。榨汁的具体过程(电机转动、刀片切割)被封装在了机器内部。

Java中的方法就是这个概念的体现:

  • 封装:将一段完成特定功能的代码块{}包裹起来,形成一个独立的单元。
  • 复用:定义一次,可以在程序的多个地方多次调用。
  • 简化代码:使程序结构更清晰、层次更分明,便于阅读和维护。

二、方法的定义与语法

一个方法的标准定义包括以下几个部分:

java

[修饰符] 返回值类型 方法名([参数类型1 参数名1, 参数类型2 参数名2, ...]) {// 方法体:实现具体功能的代码[return 返回值;] // 如果返回值类型不是void,则必须使用return语句
}

让我们来详细拆解每个部分:

1. 方法名
  • 方法的名称,遵循小驼峰命名法(如 calculateSum, getUserName)。
  • 应做到见名知意,通过名字就能大致猜出方法的功能。
2. 修饰符 (Modifier)
  • 定义方法的访问权限和特性。目前最常用的是:
    • public:公开的,任何其他类都可以访问。
    • static:静态的,属于类本身,而非类的实例。main 方法必须是 static 的。
3. 返回值类型 (Return Type)
  • 方法执行后返回给调用者的数据的类型(如 int, String, void)。
  • 如果方法不返回任何值,必须使用关键字 void
4. 参数列表 (Parameters)
  • 方法执行所需要的输入信息,写在 () 内。
  • 格式:(类型1 参数名1, 类型2 参数名2, ...)
  • 参数就像方法的“原材料”。一个方法可以有0个、1个或多个参数。
5. 方法体 (Method Body)
  • {} 括起来的代码块,包含了实现方法功能的具体语句。
6. return 语句
  • 用于结束方法,并将结果返回给调用者。
  • 如果方法的返回值类型是 voidreturn 语句可以省略,或者写成 return;(仅用于结束方法,不返回任何值)。
  • 如果返回值类型不是 void,则必须包含 return 返回值; 语句,且返回值的类型必须与声明的返回值类型兼容

三、方法的分类与示例

根据是否有参数和返回值,方法可以分为四类:

1. 无参无返回值方法

java

// 定义:打印一条分隔线
public static void printLine() {System.out.println("------------------------");
}// 调用
printLine(); // 输出:------------------------
2. 有参无返回值方法

java

// 定义:打印指定次数的Hello
public static void printHello(int count) { // int count 是形式参数for (int i = 0; i < count; i++) {System.out.println("Hello");}
}// 调用
printHello(3); // 这里的 3 是实际参数
// 输出:
// Hello
// Hello
// Hello
3. 无参有返回值方法

java

// 定义:获取一个简单的问候语
public static String getGreeting() {return "Welcome to Java!"; // 返回一个String类型的值
}// 调用
String message = getGreeting(); // 用变量接收返回值
System.out.println(message); // 输出:Welcome to Java!
4. 有参有返回值方法(最常用)

java

// 定义:计算两个整数的和
public static int add(int a, int b) { // 两个形式参数int sum = a + b;return sum; // 返回计算结果
}// 调用
int result = add(5, 3); // 传递两个实际参数
System.out.println("5 + 3 = " + result); // 输出:5 + 3 = 8
// 也可以直接使用方法的返回值
System.out.println("10 + 20 = " + add(10, 20)); // 输出:10 + 20 = 30

四、方法的调用与执行流程

调用方法:在另一个方法(如 main 方法)中,通过 方法名(参数); 的方式来执行它。

执行流程(非常重要):

  1. 程序从 main 方法开始执行。
  2. 当遇到方法调用时(如 add(5, 3);),程序会暂停当前方法的执行。
  3. 程序会跳转到被调用方法(add)的内部开始执行。
  4. 参数传递:将实参的值(53拷贝一份,传递给形参ab)。
  5. 执行被调用方法的方法体。
  6. 当执行到 return 语句或方法体结束时,被调用方法执行完毕。
  7. 程序返回到当初暂停的地方(main 方法中),并继续向下执行。如果有返回值,则用返回值代替方法调用。

示例分析

java

public class MethodFlow {public static void main(String[] args) {System.out.println("程序开始");   // 1int x = 10;                      // 2int y = 20;                      // 3int sum = add(x, y);             // 4 -> 跳转到add方法System.out.println("和是: " + sum); // 7System.out.println("程序结束");   // 8}public static int add(int a, int b) { System.out.println("正在计算加法..."); // 5return a + b;                      // 6 -> 带着结果30返回main方法}
}

输出结果

text

程序开始
正在计算加法...
和是: 30
程序结束

五、方法的重载 (Overload)

这是Java非常重要的一个特性。

  • 概念:在同一个类中,允许存在多个同名的方法,只要它们的参数列表不同即可。
  • 参数列表不同指的是:参数个数不同参数类型不同、或参数顺序不同
  • 注意返回值类型不同不足以构成重载。
  • 优点:解决了功能相似的方法,因参数不同而需要起不同名字的麻烦,提高了方法的易用性。

重载示例

java

public class Calculator {// 计算两个int数的和public static int add(int a, int b) {return a + b;}// 重载:计算三个int数的和 (参数个数不同)public static int add(int a, int b, int c) {return a + b + c;}// 重载:计算两个double数的和 (参数类型不同)public static double add(double a, double b) {return a + b;}// 重载:参数顺序不同 (但这种情况在实际开发中很少见,容易混淆)public static void printInfo(String name, int age) {System.out.println("Name: " + name + ", Age: " + age);}public static void printInfo(int age, String name) {System.out.println("Age: " + age + ", Name: " + name);}// 错误示例:仅返回值类型不同,不是重载,会编译报错// public static double add(int a, int b) {//     return (double)(a + b);// }
}// 调用
System.out.println(Calculator.add(1, 2));        // 调用add(int, int)
System.out.println(Calculator.add(1, 2, 3));     // 调用add(int, int, int)
System.out.println(Calculator.add(1.5, 2.5));    // 调用add(double, double)

JVM在调用方法时,会根据你传入的实际参数的类型和数量,自动匹配最合适的一个重载方法。


六、方法的参数传递机制:值传递

这是Java方法的一个核心且易错的特性。

  • 核心规则:Java中方法的参数传递,永远是值传递。即将实际参数值的副本传入方法内部,而参数本身不会受到影响。
  • 对于基本数据类型(如 int, double, char),传递的是值的拷贝。在方法内修改形参,不会影响实参。
  • 对于引用数据类型(如数组、对象),传递的是地址的拷贝。在方法内通过这个地址修改对象的内容(如修改数组元素、调用对象的方法),会影响实参所指向的原始对象。但如果让形参指向一个新的对象,则不会影响实参。

示例1:基本数据类型(值不受影响)

java

public static void main(String[] args) {int num = 10;changeValue(num); // 传递的是10这个值的拷贝System.out.println("main方法中的num: " + num); // 输出:10 (原值未变)
}public static void changeValue(int value) { // value是num的一个副本value = 100; // 修改的是副本的值System.out.println("changeValue方法中的value: " + value); // 输出:100
}

示例2:引用数据类型(内容受影响)

java

public static void main(String[] args) {int[] arr = {1, 2, 3};changeArray(arr); // 传递的是数组arr的地址拷贝System.out.println("main方法中的arr[0]: " + arr[0]); // 输出:100 (内容被改变了!)
}public static void changeArray(int[] array) { // array和arr指向同一个数组对象array[0] = 100; // 通过地址修改了堆内存中数组对象的内容
}

七、变量的作用域

在方法中定义的变量称为局部变量

  • 作用域:局部变量只在定义它的代码块 {} 内有效。
  • 生命周期:当方法被调用时,Java虚拟机会为其局部变量分配内存;当方法调用结束,这些局部变量所占用的内存会被自动释放
  • 重要规则:在重叠的作用域内(如嵌套的 {}),不能定义同名的局部变量。
http://www.xdnf.cn/news/1377091.html

相关文章:

  • android 嵌套webview 全屏展示 页面延伸到状态栏且不被底部导航栏遮挡
  • 高并发内存池(11)-PageCache获取Span(下)
  • 【C++标准库】<ios>详解基于流的 I/O
  • 腾讯云 CVM 上的 SpringBoot 应用避免非法访问
  • 寄存器的原理
  • YOLOv8-SMOT:一种高效鲁棒的实时小目标跟踪框架:基于切片辅助训练与自适应关联
  • 人工智能-python-深度学习-反向传播优化算法
  • ESP32使用场景及大规模物联网IoT
  • 流水线用到的Dockerfile和构建脚本build.sh
  • 如何安装 mysql-installer-community-8.0.21.0.tar.gz(Linux 详细教程附安装包下载)​
  • 神经网络学习笔记11——高效卷积神经网络架构SqueezeNet
  • 聊一聊 单体分布式 和 微服务分布式
  • 深度学习——优化函数
  • 自学嵌入式第二十九天:Linux系统编程-线程
  • flume监控文件写入 Kafka 实战:解耦应用与消息队列的最佳实践
  • 在语言模型监督式微调(SFT)中的 负对数似然(Negative Log-Likelihood, NLL)等价于最大化似然
  • 软考-系统架构设计师 管理信息系统(MIS)详细讲解
  • 为什么编码智能体可以重塑开发范式?
  • 【Mascaret】QGIS中Mascaret插件的使用
  • ESP8266:Arduino学习
  • 高并发内存池(12)-ThreadCache回收内存
  • 【HTML】隐藏滚动条但保留功能
  • 什么是AI+?什么是人工智能+?
  • redis---set详解
  • ICCV 2025 | 清华IEDA提出GUAVA,单图创建可驱动的上半身3D化身!实时、高效,还能捕捉细腻的面部表情和手势。
  • 《MongoDB 常用命令详解:从数据库操作到高级查询》
  • Windows/Linux 环境下 Jmeter 性能测试的安装与使用
  • 未成功:使用 Nginx 搭建代理服务器(正向代理 HTTPS 网站)
  • Linux学习-TCP并发服务器构建
  • 在 Windows 上部署 Go 语言开发环境