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

【java基础语法】------ 数组

1. 数组

在 Java 面向对象编程中,数组(Array) 是最基础、最常用的数据结构之一。它是一种容器,用于存储相同数据类型的多个值,是处理批量数据的核心工具。


1.1 数组概述

1.1.1 什么是数组?

数组是一种有序的、固定长度的容器,用于存储多个相同类型的元素。

  • 它可以看作是一个“盒子”,里面装着若干个相同类型的数据;
  • 每个数据都有一个唯一的索引(下标),从 0 开始编号;
  • 数组一旦创建,其长度就不可改变(除非重新创建);
  • 所有元素必须是同一数据类型(如全部为 intStringdouble)。

1.2 数组定义

1.2.1 定义格式

Java 支持两种等价的语法来定义数组,推荐使用第一种,更符合“类型 + []”的阅读习惯。

格式示例
格式一:数据类型 [] 数组名int[] array;
格式二:数据类型 数组名 []int array[];

1.2.2 类型匹配规则

数组作为容器,其数据类型决定了能存储哪些值。Java 在存储数据时会自动进行隐式类型转换(如果允许),但需注意边界。

数组类型可存储的数据类型说明
int[]byte, short, int, char自动提升(隐式转换)
double[]byte, short, int, long, float, double全部可存储,自动提升

1.3 静态初始化

静态初始化是指在定义数组时,直接指定元素值,由 JVM 自动确定数组长度并完成内存分配。


1.3.1 完整格式

数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ...};
  • 明确使用 new 关键字;
  • 指定数组类型和初始值;
  • 编译器根据元素个数自动推断长度。

示例:

int[] arr = new int[]{1, 12, 13, 14};

1.3.2 简化格式

数据类型[] 数组名 = {元素1, 元素2, ...};
  • 省略 new 和类型重复,更简洁;
  • 是完整格式的语法糖(编译后等价);

示例:

int[] arr = {1, 12, 13, 14};

1.3.3 数组的地址值

数组是对象,其变量存储的是堆内存中的地址值
当打印数组变量时,输出的是该地址的字符串表示形式,格式如下:

[类型@十六进制地址]
  • [:表示这是一个数组;
  • 类型:如 I 表示 intD 表示 doubleLjava.lang.String; 表示 String
  • @:分隔符;
  • 十六进制字符串:真正的内存地址(JVM 生成)。

示例:

int[] arr = {1, 2, 3};
System.out.println(arr); // 输出:[I@776ec8df

解释:

  • [I:表示 int 类型的数组;
  • @776ec8df:十六进制地址,唯一标识该数组对象。

1.3.4 示例代码

package com.itheima.demo1;public class ArrayDemo1 {public static void main(String[] args) {// 数组静态初始化:// 完整格式:数据类型[] 数组名 = new 数据类型[]{元素...};// 简化格式:数据类型[] 数组名 = {元素...};int[] arr1 = new int[]{1, 12, 13, 14};int[] arr2 = {1, 12, 13, 14};String[] arr3 = new String[]{"张三", "李四", "王五"};String[] arr4 = {"张三", "李四", "王五"};double[] arr5 = new double[]{1.1, 2.2, 3.3, 4.4};double[] arr6 = {1.1, 2.2, 3.3, 4.4};}
}

1.4 数组元素访问

数组中的每个元素通过 索引(下标) 访问,索引从 0 开始,依次递增。

1.4.1 访问格式:

数组名[索引]
  • 读取元素int num = arr[0];
  • 修改元素arr[0] = 100;

1.4.2 示例代码:

package com.itheima.demo1;public class ArrayDemo2 {public static void main(String[] args) {// 定义并初始化数组int[] arr = {1, 12, 13, 14};// 获取元素:通过索引访问(从0开始)int num = arr[0];System.out.println(num);// 修改元素:通过索引赋值arr[0] = 100;System.out.println(arr[0]); }
}

在这里插入图片描述


1.5 数组遍历

数组遍历是指依次访问数组中所有元素的过程,常用于打印、求和、统计等操作。

1.5.1常用方式:for 循环

for (int i = 0; i < arr.length; i++) {// 处理 arr[i]
}

1.5.2 示例1:求和

package com.itheima.demo1;public class ArrayTest1 {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}System.out.println("和为:" + sum); }
}

在这里插入图片描述

1.5.3 示例2:统计满足条件的元素个数

package com.itheima.demo1;public class ArrayTest2 {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int count = 0;for (int i = 0; i < arr.length; i++) {if (arr[i] % 3 == 0) {count++;}}System.out.println("个数为:" + count); }
}

在这里插入图片描述


1.6 动态初始化

动态初始化是在创建数组时指定长度,由系统自动分配默认初始值。

1.6.1 格式:

数据类型[] 数组名 = new 数据类型[长度];

1.6.2 默认初始化值规律:

类型默认值
整数(int, byte, short, long)0
小数(float, double)0.0
字符(char)‘\u0000’(空格)
布尔(boolean)false
引用类型(String, 对象)null

1.6.3 示例代码:

package com.itheima.demo1;public class ArrayTest4 {public static void main(String[] args) {// 动态初始化:指定长度,系统赋默认值String[] arr = new String[50];arr[0] = "hello";arr[1] = "world";System.out.println(arr[0]); // 输出:helloSystem.out.println(arr[1]); // 输出:worldSystem.out.println(arr[2]); // 输出:null(未赋值)}
}

在这里插入图片描述


1.7 动态 vs 静态初始化的区别

特性动态初始化静态初始化
指定内容只指定长度指定具体元素
使用场景元素未知,只知数量(如键盘输入)元素已知且明确
示例int[] arr = new int[5];int[] arr = {11, 22, 33};

小结:

  • 动态:先占位,后赋值;
  • 静态:直接赋值,无需手动设置长度。

1.8 索引越界异常

当访问的索引超出数组合法范围时,会抛出 ArrayIndexOutOfBoundsException

1.8.1 错误示例:

package com.itheima.demo1;public class ArrayTest5 {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};System.out.println(arr[10]); // 错误!索引最大为 4}
}

在这里插入图片描述

避免方法:

  • 使用 arr.length 控制循环边界;
  • 在访问前判断索引是否有效。

1.9 内存分析

1.9.1 Java 内存分配

在这里插入图片描述

Java 程序运行时,内存主要划分为以上几个区域,其中与数组和变量密切相关的主要是 栈内存(Stack)堆内存(Heap)

1.9.1.1 栈内存(Stack)
  • 用于存储局部变量(包括基本数据类型变量和引用类型变量);
  • 方法调用时,会在栈中创建一个“栈帧”,方法执行完毕后自动释放;
  • 特点:存储速度快、生命周期短、空间有限
2. 堆内存(Heap)
  • 用于存储 new 创建的对象和数组
  • 所有通过 new 关键字创建的实体(如 new int[3]new String[5])都存在于堆中;
  • 特点:空间大、由垃圾回收器(GC)自动管理、生命周期由引用决定
3. 方法区(Method Area,含常量池)
  • 存储类信息、静态变量、常量(如字符串字面量 "hello")等;
  • 在 JDK 8 之后,方法区由 元空间(Metaspace) 实现。

在这里插入图片描述

1.9.2 一维数组内存分析

1.9.2.1 正常一维数组
一维数组的动态初始化过程

在这里插入图片描述

注:通过 new int[2] 在堆内存中创建一个长度为 2 的整型数组,系统自动为每个元素赋予默认初始值 0;同时,在栈内存中声明一个数组引用变量arr,并将其指向堆中新建的数组对象,从而完成数组的创建。

一维数组地址的打印

在这里插入图片描述

一维数组具体元素的打印

在这里插入图片描述

注:程序执行 sout(arr[1]) 时,JVM 根据栈中引用变量 arr 指向的堆内存地址,定位到数组对象,并通过索引 1 访问该位置存储的元素值(初始为 0),最终将该值输出至控制台。

一维数组具体元素的覆盖

在这里插入图片描述

注:程序执行 arr[0] = 11;arr[1] = 22; 时,JVM 通过栈中引用变量 arr 定位到堆内存中的数组对象,分别将索引 01 处的默认值 0 替换为 1122,完成对数组元素的赋值操作。

打印覆盖后的元素

在这里插入图片描述

一维数组的静态初始化过程

在这里插入图片描述

注:JVM 在堆内存中创建一个长度为 3 的新数组对象,并将初始值 {33, 44, 55} 直接赋给对应位置。同时,在栈内存中声明引用变量 arr2,并将其指向该堆中数组的地址(如 0x4c966a),完成静态初始化过程。

一维数组地址的打印

在这里插入图片描述

一维数组具体元素的打印

在这里插入图片描述

1.9.2.2 两个一维数组指向同一块空间
静态初始化一个一维数组

在这里插入图片描述

将一维数组arr1 的 地址值赋值给另一个一维数组arr2

在这里插入图片描述

通过两种方式访问同一个元素

在这里插入图片描述

元素覆盖

在这里插入图片描述

通过两种方式访问同一个被覆盖的元素

在这里插入图片描述

小结
  • 当两个数组引用指向堆内存中的同一块数组空间时,它们共享同一个数组对象。
  • 对其中一个数组的元素进行修改,实质上是修改了堆中共享的数据,因此另一个数组再次访问该元素时,得到的将是修改后的结果。

1.10 二维数组

1.10.1 静态初始化

静态初始化是指在声明时直接指定所有元素的值

  • 完整格式
    数据类型[][] 数组名 = new 数据类型[][]{{元素...}, {元素...}};
    
  • 简化格式(推荐)
    数据类型[][] 数组名 = {{元素...}, {元素...}};
    

建议:每个一维数组单独占一行,提升代码可读性:


1.10.2 动态初始化

动态初始化是在声明时指定数组的行数和列数,系统自动分配空间并用默认值填充。

  • 格式
    数据类型[][] 数组名 = new 数据类型[行数][列数];
    
    • m 表示可以存放多少个一维数组(即行数)
    • n 表示每个一维数组可存放多少个元素(即列数)

1.10.3 数组内存图分析

1.10.3.1 正常情况
二维数组的内存结构(动态初始化)

在这里插入图片描述

注:执行 int[][] arr = new int[2][3]; 时,JVM 在堆中创建一个长度为 2 的二维数组对象(地址如 0x0011),其包含两个引用,分别指向两个长度为 3 的一维数组(地址 0x00220x0033),所有元素默认为 0;栈中变量 arr 指向该二维数组对象。

访问第一行数组

在这里插入图片描述

注:arr[0] 表示获取二维数组的第一行一维数组的引用,即指向堆中地址 0x0022 的数组对象,可进一步访问其元素。

访问指定元素

在这里插入图片描述

注:arr[0][1] 表示先通过 arr[0] 定位到第一行数组(0x0022),再访问该数组索引为 1 的元素,对应堆中值为 0 的位置。

1.10.3.2 特殊情况
二维数组的不规则结构(锯齿数组)

在这里插入图片描述

注:JVM 在堆中创建一个长度为 2 的二维数组对象(地址如 0x0011),其两个元素初始为 null;栈中引用 arr 指向该对象。随后创建两个长度不同的数组 arr1 = {11, 22}arr2 = {44, 55, 66},分别位于堆中不同位置。JVMrow1row2 的地址分别赋给 arr 的第 0 行和第 1 行,形成每行长度不同的“锯齿数组”。

二维数组的引用赋值

在这里插入图片描述

注:JVM 在堆中创建一个长度为 2 的二维数组对象(地址如 0x0011),其每一行都指向一个长度为 3 的一维数组,所有元素默认初始化为 0;栈中变量 arr 指向该对象。随后定义两个独立的一维数组 arr1 = {11, 22}arr2 = {44, 55, 66},分别存储在堆中(地址如 0x00AA0x00BB)。当执行 arr[0] = arr1;arr[1] = arr2; 时,JVM 将这两个一维数组的地址赋给 arr 的第 0 行和第 1 行,覆盖了原本由 new int[3] 创建的数组,最终形成一个每行长度不同的不规则二维数组结构。


1.10.4 基础代码示例

package com.itheima.demo1;public class ArrayTest7 {public static void main(String[] args) {//1.静态初始化//完整格式:数据类型[][] 数组名 = new 数据类型[][]{{元素...},{元素...}};int[][] arr1 =new int[][]{{1,2,3},{4,5,6}};//简化格式:数据类型[][] 数组名 = {{元素...},{元素...}};int[][] arr2 = {{1,2,3},{4,5,6}};//建议每个一维数组占一行,方便阅读int[][] arr3={{1,2,3},{4,5,6,7,8}};//2.动态初始化//完整格式:数据类型[][] 数组名 = new 数据类型[行数][列数];//表示创建一个含有3个一维数组(每个一维数组有5个元素)的二维数组int[][] arr4=new int[3][5];//3.获取数组元素//获取数组中索引为0的元素(即第一个一维数组的地址值)System.out.println(arr1[0]);//arr[0]: 获取第一个一维数组的地址//[0]: 获取第一个一维数组中索引为0的元素 " 1 "System.out.println(arr1[0][0]);//4.遍历// 外层循环:遍历二维数组 arr3 的每一行for (int i = 0; i < arr3.length; i++) {// 内层循环:遍历当前行 arr3[i] 中的每一个元素for (int j = 0; j < arr3[i].length; j++) {// 打印当前元素 arr3[i][j]System.out.print(arr3[i][j] + " ");}}}
}

在这里插入图片描述

注意:

  • arr3.length:获取二维数组的行数;
  • arr3[i].length:获取第 i 行一维数组的长度(支持不规则二维数组);
  • 使用嵌套循环遍历每一行、每一列的元素。

1.10.5 综合示例

在这里插入图片描述

package com.itheima.demo1;public class ArrayDemo4 {public static void main(String[] args) {// 定义一个二维数组,表示一年中4个季度(每行一个季度),每个季度有3个月的营业额int[][] yearArrArr = {{22, 66, 44},  // 第一季度{77, 33, 88},  // 第二季度{25, 45, 65},  // 第三季度{11, 66, 99}   // 第四季度};int yearSum = 0; // 用于累计全年总营业额// 遍历每个季度(外层循环)for (int i = 0; i < yearArrArr.length; i++) {int[] quarterArr = yearArrArr[i]; // 获取第 i 个季度的月营业额数组int sum = getSum(quarterArr);     // 调用方法计算该季度总营业额System.out.println("第" + (i + 1) + "个季度的总营业额为:" + sum);yearSum += sum; // 累加到全年总营业额}System.out.println("总营业额为:" + yearSum); // 输出全年总营业额}// 求单个季度(即一个一维数组)的营业额总和public static int getSum(int[] arr) {int sum = 0;// 遍历数组中的每个月营业额并累加for (int i = 0; i < arr.length; i++) {sum += arr[i];}return sum; // 返回该季度总营业额}}

在这里插入图片描述


1.11 对象数组练习:

需求:

  1. 初始化数据 定义一个长度为3的数组。
    数组中存储1~3名学生对象作为初始数据。
    学生对象属性:学号(id)、姓名、年龄。
    要求:学号和姓名各不相同。

  2. 添加学生 添加一个新学生对象。
    添加前需判断学号是否唯一,若已存在则不能添加。
    在添加完成后,遍历并输出所有学生信息。

  3. 删除学生 通过学号(id)删除学生信息。
    若存在,则删除成功;若不存在,则提示“删除失败”。
    删除操作完成后,再次遍历所有学生信息。

  4. 查询并修改 查询指定学号的学生。
    如果存在,则将其年龄增加1岁。
    修改操作完成后,再次遍历所有学生信息。

代码实现:

在这里插入图片描述

Student类的定义:
package test5;public class Student {private int id;private String name;private int age;//构造方法public Student() {}public Student(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}//getter和setter方法public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
需求1,2的实现
package test5;import java.util.Scanner;public class StudentTest1 {public static void main(String[] args) {// 创建长度为3的学生数组,并初始化3个学生对象Student[] arr = new Student[3];Student stu1 = new Student(1, "张三", 23);Student stu2 = new Student(2, "李四", 24);Student stu3 = new Student(3, "王五", 25);arr[0] = stu1;arr[1] = stu2;arr[2] = stu3;// 尝试添加新学生(id=4)Student stu4 = new Student(4, "林六", 27);// 检查id是否已存在if (contains(arr, stu4)) {System.out.println("当前id重复,请修改之后再添加");} else {int count = getLength(arr); // 获取当前有效元素个数if (count == arr.length) {  // 数组已满,需扩容Student[] newArr = addArr(arr); // 扩容数组newArr[count] = stu4;           // 添加新元素printArr(newArr);               // 打印结果} else {arr[count] = stu4;  // 直接添加到第一个空位printArr(arr);      // 打印结果}}}// 打印数组中所有非null学生信息public static void printArr(Student[] arr) {for (int i = 0; i < arr.length; i++) {if (arr[i] != null) {System.out.println(arr[i].getId() + ", " + arr[i].getName() + ", " + arr[i].getAge());}}}// 扩容:创建一个比原数组长1的新数组,并复制元素public static Student[] addArr(Student[] arr) {Student[] newArr = new Student[arr.length + 1];for (int i = 0; i < arr.length; i++) {newArr[i] = arr[i];}return newArr;}// 判断数组中是否已存在相同id的学生public static boolean contains(Student[] arr, Student stu) {int id = stu.getId();for (int i = 0; i < arr.length; i++) {if (arr[i] != null && id == arr[i].getId()) {return true;}}return false;}// 统计数组中非null元素的个数public static int getLength(Student[] arr) {int count = 0;for (int i = 0; i < arr.length; i++) {if (arr[i] != null) {count++;}}return count;}
}
运行结果示例:

在这里插入图片描述

需求3,4的实现
package test5;import java.util.Scanner;public class StudentTest2 {public static void main(String[] args) {// 创建长度为3的学生数组,并初始化3个学生对象Student[] arr = new Student[3];arr[0] = new Student(1, "张三", 23);arr[1] = new Student(2, "李四", 24);arr[2] = new Student(3, "王五", 25);// 删除操作:读取用户输入的idSystem.out.println("请输入要删除信息的学生id:");Scanner sc = new Scanner(System.in);int deleteId = sc.nextInt();// 查找对应id的索引int deleteIndex = getIndex(deleteId, arr);if (deleteIndex >= 0) {arr[deleteIndex] = null; // 删除:置为null} else {System.out.println("没有此id,删除失败");}printArr(arr); // 打印删除后的数组// 修改操作:读取要修改的学生idSystem.out.println("请输入要修改信息的学生id:");int checkId = sc.nextInt();int checkIndex = getIndex(checkId, arr);if (checkIndex >= 0) {// 示例修改:年龄+1arr[checkIndex].setAge(arr[checkIndex].getAge() + 1);} else {System.out.println("没有此id,修改失败");}printArr(arr); // 打印修改后的数组}// 根据id查找学生在数组中的索引,未找到返回-1public static int getIndex(int id, Student[] arr) {for (int i = 0; i < arr.length; i++) {if (arr[i] != null && id == arr[i].getId()) {return i;}}return -1;}// 打印数组中所有非null学生的信息public static void printArr(Student[] arr) {for (int i = 0; i < arr.length; i++) {if (arr[i] != null) {System.out.println(arr[i].getId() + ", " + arr[i].getName() + ", " + arr[i].getAge());}}}
}
运行结果示例:

在这里插入图片描述

http://www.dtcms.com/a/566952.html

相关文章:

  • 如何使用vite快速搭建一个vue3的项目?
  • 网站长期建设 运营计划网站升级改版需要几天
  • 网站没有织梦后台企业网站程序
  • 中企动力建的网站如何展览馆网站建设
  • 网站优怎么做怎样弄微信公众号
  • 网站开发语言学习wordpress要求配置
  • 网站建设黄荣新手如何自学编程
  • 网站备案信息开发公司工程部岗位职责
  • 鄱阳县建设局网站凯盛建设公司网站
  • 网站免费推广方法可以做网站的域名后缀
  • pr效果做的好的网站有哪些长洲网站建设
  • 2025年SEVC SCI2区,具有互补和集成变异策略的双阶段自适应差分进化算法用于求解全局优化问题,深度解析+性能实测
  • Ax=b超静定方程组,已知初始解x0情况下得快速解法
  • 做淘宝客网站备案要怎么写广西响应式网站哪家好
  • 公司外贸网站建设什么网站做视频最赚钱
  • 新媒体 网站建设 管理规范百度推广退款电话
  • 关于dw做网站云服务器网站搭建教程
  • 大学生创业服务网站建设方案项目书江苏华江建设集团有限公司网站
  • 宠物医院网站建设wordpress 存储位置
  • 移动办公型网站开发网络营销推广的ppt
  • 建网站的专业公司怎么利用代码做网站
  • 站长工具海角推广平台的方式有哪些
  • 网站备案ip镇江市网站建设设计
  • 高端做网站多少钱内链好的网站
  • 深圳开发网站的公司哪家好ftp 网站文件
  • 华为-AI智算网络学习-1
  • 网站常规seo优化步骤it培训班大概需要多少钱
  • 广州住房公积金建设银行预约网站计算机培训机构哪个最好
  • 安卓网站开发ui婚庆公司网站建设策划书.doc
  • 做商城微信网站怎样营销网站建设