Java 基础--数组(Array):存储数据的“排排坐”

作者:IvanCodes

发布时间:2025年5月1日🤓

专栏:Java教程


大家好!👋 咱们在编程时,经常需要处理一批相同类型的数据,比如班级里所有同学的成绩 💯、一周每天的最高气温 🌡️、或者购物车里的商品列表 🛒。如果为每个数据都声明一个单独的变量(score1, score2, score3…),那代码不得写“疯”了?🤯

这时候,就轮到 Java 中的一个基础且重要的数据结构登场了——数组 (Array)!你可以把它 想象成一排带编号的储物柜 或者一个鸡蛋托 🥚,专门用来整齐地存放 多个相同类型 的数据。今天,我们就来把数组这个“老朋友”彻底搞明白!

一、 数组到底是个啥?🤔

简单来说,数组就是一个固定大小容器 📦,里面存放的元素必须是相同的数据类型

几个关键特性要记住:

  1. 类型统一:一个 int 数组里只能放 int,一个 String 数组里只能放 String。不能混装!🚫
  2. 长度固定 : 数组一旦创建,它的长度(能装多少个元素)就不能再改变了!这是数组最核心的限制之一 ⚠️。
  3. 连续存储 (通常): 在内存中,数组的元素通常是连续存放的,这使得通过索引访问元素非常 ⚡️。
  4. 索引访问 : 每个元素都有一个唯一的索引(编号),从 0 开始!通过索引可以快速定位和访问元素。

二、 创建和使用数组 ✍️

怎么在代码里用数组呢?主要分两步:声明初始化

2.1 声明数组引用

告诉编译器:“我要一个能指向某种类型数组的变量”。

// 推荐的声明方式
int[] scores;
String[] names;
double[] prices;// C/C++ 风格的声明方式 (也能用,但不推荐)
// int scores[];
// String names[];

注意:这只是声明了一个引用变量,它现在还是 null,并没有指向任何实际的数组内存空间。

2.2 初始化数组(分配空间/赋值)

初始化才是真正创建数组对象、分配内存空间的时候。有两种主要方式:

方式一:使用 new 指定长度

这是最常用的方式,你知道需要多大的数组,但还不确定里面的具体值。

// 创建一个能存放 5 个 int 的数组
scores = new int[5]; // 分配了 5 个 int 的空间// 创建一个能存放 10 个 String 的数组
names = new String[10]; // 分配了 10 个 String 引用的空间// 声明和初始化可以合并
double[] salaries = new double[50];

重点📌: 使用 new 创建数组后,里面的元素会被自动赋予默认值

  • 数值类型 (int, double etc.): 00.0
  • boolean: false
  • char: \u0000 (空字符)
  • 引用类型 (String, Object etc.): null

方式二:静态初始化 (直接提供元素值)

如果你在创建数组时就已经知道里面要放哪些元素了,可以用这种更简洁的方式。编译器会根据你提供的值自动确定数组的长度。

// 直接提供初始值,长度由编译器确定 (这里是 4)
int[] initialScores = {90, 85, 92, 78};// 声明和静态初始化合并
String[] weekdays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};// 不能分开写!下面这样是错误的 ❌
// int[] numbers;
// numbers = {1, 2, 3}; // 编译错误
// 必须这样写:
int[] numbers;
numbers = new int[]{1, 2, 3}; // 或者声明时就初始化

2.3 访问数组元素:靠索引 [] 👉

数组的核心操作就是通过索引来存取元素。记住:索引从 0 开始! 非常非常重要! 🚨

public class ArrayAccess {public static void main(String[] args) {String[] fruits = {"Apple <🍎>", "Banana <🍌>", "Orange <🍊>"}; // 长度为 3// 访问元素 (索引 0, 1, 2)System.out.println("First fruit: " + fruits[0]); // Apple <🍎> (索引 0)System.out.println("Second fruit: " + fruits[1]); // Banana <🍌> (索引 1)System.out.println("Third fruit: " + fruits[2]); // Orange <🍊> (索引 2)// 修改元素fruits[1] = "Grape <🍇>"; // 把第 2 个元素 (索引 1) 改成 GrapeSystem.out.println("Second fruit now: " + fruits[1]); // Grape <🍇>// 尝试访问不存在的索引?后果很严重!// System.out.println(fruits[3]); // 运行时错误💥: ArrayIndexOutOfBoundsException}
}

2.4 获取数组长度:.length 属性 📏

想知道数组能装多少东西?用 .length 属性(注意:是属性,不是方法,后面没有括号 (),这点和 Stringlength() 方法不同,容易混淆!)。

int[] data = new int[10];
System.out.println("Length of data array: " + data.length); // Output: 10String[] colors = {"Red", "Green", "Blue"};
System.out.println("Number of colors: " + colors.length); // Output: 3

.length循环遍历数组时特别有用。

三、 遍历数组:挨个“点名” 🚶‍♀️🚶‍♂️

遍历数组就是按顺序访问数组中的每一个元素,通常用循环来实现。

3.1 使用传统 for 循环

最灵活的方式,因为你可以拿到当前的索引 i

public class ForLoopArray {public static void main(String[] args) {double[] readings = {12.5, 13.1, 11.8, 12.9};System.out.println("Sensor Readings:");// 循环条件通常是 i < array.lengthfor (int i = 0; i < readings.length; i++) {System.out.println("Reading at index " + i + ": " + readings[i]);}}
}

3.2 使用增强型 for 循环 (for-each)

如果不需要关心索引,只是想依次处理每个元素,这种方式更简洁易读

import java.util.ArrayList; // 只是为了演示集合遍历
import java.util.List;public class ForEachArray {public static void main(String[] args) {char[] vowels = {'a', 'e', 'i', 'o', 'u'};System.out.print("Vowels: ");// 依次取出 vowels 数组中的每个 char 赋给变量 vowelfor (char vowel : vowels) {System.out.print(vowel + " ");}System.out.println(); // 输出: a e i o u// 同样适用于集合 (比如 ArrayList)// List<String> names = new ArrayList<>(); ...// for (String name : names) { ... }}
}

如何选择? 如果需要索引(比如要根据索引修改元素,或者需要知道当前是第几个元素),用传统 for。如果只是读取每个元素的值,增强型 for 通常更好

四、 数组的“常见烦恼” 😩💥

使用数组时,有几个经典错误你很可能会遇到:

  1. ArrayIndexOutOfBoundsException <💥>: 这是最常见的数组错误!当你试图访问一个不存在的索引时(比如索引 < 0,或者索引 >= array.length),就会抛出这个运行时异常。写循环时要特别小心边界条件!
  2. NullPointerException : 如果你的数组引用变量本身是 null(即它没有指向任何数组对象),而你试图访问它的 .length 属性或者通过索引访问元素(如 nullArray[0]),就会得到这个运行时异常使用数组前,确保它已经被正确初始化了!
  3. 长度固定不变 <🔒>: 前面强调过,数组长度一旦确定就不能改。如果你的程序需要一个可以动态增删元素的容器,那么 Java 集合框架中的 ArrayList 等类通常是更好的选择

五、 超出基础:多维数组Arrays 工具类 ▦🛠️

5.1 多维数组

你可以创建“数组的数组”,最常见的是二维数组,可以把它想象成一个表格或矩阵 ▦。

// 创建一个 3行 4列 的 int 二维数组
int[][] matrix = new int[3][4];// 静态初始化
String[][] board = {{"X", "O", "X"},{"O", "X", "O"},{"X", "O", "X"}
};// 访问元素需要两个索引
matrix[0][1] = 5; // 设置第 1 行第 2 列 (索引都是从 0 开始)
System.out.println("Board[1][1]: " + board[1][1]); // Output: X

遍历二维数组通常需要嵌套循环

5.2 java.util.Arrays 工具类 <🛠️>

Java 提供了一个非常有用的 Arrays 类(在 java.util 包下),里面包含了很多操作数组static方法,能省不少事:

  • Arrays.toString(array): 把数组转换成易于阅读的字符串形式,方便打印调试,强烈推荐!👍
  • Arrays.sort(array): 对数组进行排序(原地排序)。
  • Arrays.fill(array, value): 用指定值填充整个数组
  • Arrays.copyOf(originalArray, newLength): 复制数组的一部分或全部到一个新的数组(可以用来变相“扩展”数组)。
  • Arrays.equals(array1, array2): 比较两个数组内容是否相等(注意,不是用 == 比地址)。
import java.util.Arrays; // <--- 别忘了导入!public class ArraysUtilDemo {public static void main(String[] args) {int[] nums = {5, 2, 8, 1, 9};// 好看的打印方式System.out.println("Original array: " + Arrays.toString(nums));// 排序Arrays.sort(nums);System.out.println("Sorted array: " + Arrays.toString(nums));// 填充int[] filled = new int[5];Arrays.fill(filled, -1);System.out.println("Filled array: " + Arrays.toString(filled));// 复制 (取前 3 个元素)int[] copied = Arrays.copyOf(nums, 3); // nums 已经是排序后的 {1, 2, 5, 8, 9}System.out.println("Copied first 3: " + Arrays.toString(copied));}
}

六、总结 🏁

数组是 Java 中存储固定数量相同类型元素的基础数据结构。

  • 核心特性类型统一长度固定索引访问 (从 0 开始)。
  • 创建方式new Type[size] 或静态初始化 {...}
  • 访问与长度:使用 array[index] 访问,.length 获取长度。
  • 遍历:常用 for 或增强 for 循环。
  • 常见陷阱 🚨ArrayIndexOutOfBoundsException, NullPointerException, 长度固定限制。
  • 好帮手 <🛠️>:java.util.Arrays 类提供了很多实用方法。

虽然 ArrayList 等集合类在灵活性上更胜一筹,但数组性能(尤其是访问速度)和表示固定大小数据集时仍然有其优势,并且是理解集合类的基础。所以,扎实掌握数组非常重要!


七、练练手,检验成果!✏️🧠

来,动手写写代码,巩固一下!

⭐ 基础操作 ⭐

  1. 声明一个可以存放 10 个 double 类型数据的数组 prices,并将其所有元素初始化为 9.99 (使用循环或 Arrays.fill)。
  2. 创建一个 String 数组 colors,包含 “Red”, “Green”, “Blue”, “Yellow”。然后,修改第三个元素 (“Blue”) 为 “Purple”,并打印修改后的数组内容 (使用 Arrays.toString)。

⭐ 循环与计算 ⭐

  1. 给定一个 int 数组 scores = {88, 92, 75, 98, 85},计算并打印数组中所有分数的平均值 (注意结果可能是小数)。
  2. 查找数组 int[] data = {5, -2, 9, 15, -8, 1} 中的最大值,并打印出来。

⭐ 概念辨析 ⭐

  1. 尝试解释为什么数组的索引是从 0 开始而不是从 1 开始?(提示:可以从内存地址和偏移量角度思考,或说明其历史渊源和编程习惯)
  2. 比较数组 (int[]) 和 ArrayList<Integer> 的主要区别,尤其是在大小和类型方面。

八、参考答案 ✅💡

⭐ 基础操作答案 ⭐

1.初始化 prices 数组:

import java.util.Arrays;public class InitPrices {public static void main(String[] args) {double[] prices = new double[10];// 方法一:使用循环// for (int i = 0; i < prices.length; i++) {//     prices[i] = 9.99;// }// 方法二:使用 Arrays.fill (更推荐)Arrays.fill(prices, 9.99);System.out.println("Initialized prices: " + Arrays.toString(prices));}
}

2.修改 colors 数组:

import java.util.Arrays;public class ModifyColors {public static void main(String[] args) {String[] colors = {"Red", "Green", "Blue", "Yellow"};System.out.println("Original colors: " + Arrays.toString(colors));// 第三个元素索引是 2if (colors.length > 2) { // 做个简单检查防止越界colors[2] = "Purple <💜>";}System.out.println("Modified colors: " + Arrays.toString(colors));// 输出: Modified colors: [Red, Green, Purple <💜>, Yellow]}
}

⭐ 循环与计算答案 ⭐

3.计算平均分:

import java.util.Arrays;public class AverageScore {public static void main(String[] args) {int[] scores = {88, 92, 75, 98, 85};if (scores.length == 0) {System.out.println("Array is empty, cannot calculate average.");return;}int sum = 0;for (int score : scores) {sum += score;}// 注意:为了得到精确的小数结果,需要将 sum 或 length 转为 doubledouble average = (double) sum / scores.length;// 或者 double average = sum * 1.0 / scores.length;System.out.println("Scores: " + Arrays.toString(scores));System.out.println("Average score: " + average); // 输出: Average score: 87.6}
}

4.查找最大值:

import java.util.Arrays;public class FindMaxValue {public static void main(String[] args) {int[] data = {5, -2, 9, 15, -8, 1};if (data.length == 0) {System.out.println("Array is empty.");return;}int max = data[0]; // 假设第一个元素是最大值for (int i = 1; i < data.length; i++) {if (data[i] > max) {max = data[i]; // 如果找到更大的,更新 max}}System.out.println("Data: " + Arrays.toString(data));System.out.println("Maximum value: " + max); // 输出: Maximum value: 15}
}

⭐ 概念辨析答案 ⭐

5.为什么索引从 0 开始? 这主要是历史原因和底层实现效率的考虑。在 C 语言(Java 的重要祖先)及更早的语言中,数组名通常代表数组第一个元素在内存中的起始地址。访问数组元素 array[i],实际上是计算 起始地址 + i * 每个元素的大小 来找到第 i+1 个元素的地址。如果索引从 0 开始,那么访问第一个元素 array[0] 就是 起始地址 + 0 * size,即起始地址本身,计算最简单、最高效。如果从 1 开始,访问第一个元素 array[1] 就需要计算 起始地址 + (1-1) * size,多了一步减法。这种从 0 开始的索引(称为 zero-based indexing)已经成为 C 家族语言(包括 C++, Java, C#, JavaScript 等)的编程惯例

6.int[] vs ArrayList<Integer> 区别:

  • 大小:
    • int[]: 大小固定。一旦创建,长度不能改变
    • ArrayList<Integer>: 大小可变。可以动态添加或删除元素,其内部容量会自动调整(虽然可能涉及性能开销)。
  • 类型:
    • int[]: 存储的是基本数据类型 int 的值。
    • ArrayList<Integer>: 存储的是包装类 <font color="purple">Integer</font>对象引用。它不能直接存储基本类型 int(但 Java 的自动装箱/拆箱机制使得使用起来很像在存取 int)。
  • 功能: ArrayList 提供了更多现成的方法(如 add, remove, contains, size 等),而数组功能相对基础(主要靠索引和 Arrays 工具类)。
  • 性能: 对于固定大小频繁访问的场景,数组通常比 ArrayList 性能稍好(特别是对于基本类型数组,避免了装箱/拆箱开销和对象引用的开销)。

希望这篇关于数组的笔记能帮你打下坚实的基础!用熟了它,再去看集合框架就会感觉轻松很多!如果觉得有帮助,别忘了 点赞👍、收藏⭐、关注 哦!感谢!💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/78028.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS常用属性_(进阶)

目录 1.尺寸单位与颜色 &#xff08;1&#xff09;尺寸 &#xff08;2&#xff09;颜色 常用2种 &#xff08;3&#xff09;颜色属性值&#xff08;透明度&#xff09; 例如&#xff1a; 2.字体属性font 例如&#xff1a; **顺序 3.文本属性 ​编辑例如&#xff1a; …

【RabbitMQ】保证消息不丢失

要确保 RabbitMQ 在消费者&#xff08;Python 服务&#xff09;重启或挂掉时消息不丢失&#xff0c;需结合 消息持久化、确认机制&#xff08;ACK&#xff09; 和 死信队列&#xff08;DLX&#xff09; 实现高可靠性&#xff1a; 1. 消息持久化&#xff08;Durability&#xff…

Python基本语法(控制语句)

#控制语句 Python语言的控制语句和其他编程语言类似&#xff0c;常用的有if…else、while、for语句。 案例2一7控制语句 第1组代码&#xff0c;说明if-else语句&#xff1a; #1 print(\n1,if) x,y,z10,20,5 if x>y:print(x>y) else:print(x<y)输出结果: 1,if x<…

并发设计模式实战系列(10):Balking(犹豫模式)

&#x1f31f; 大家好&#xff0c;我是摘星&#xff01; &#x1f31f; 今天为大家带来的是并发设计模式实战系列&#xff0c;第10章Balking&#xff08;犹豫模式&#xff09;&#xff0c;废话不多说直接开始~ 目录 一、核心原理深度拆解 1. 状态守护机制 2. 与状态模式的…

【强化学习系列】贝尔曼方程

首先回顾状态价值函数和动作价值函数的定义&#xff1a; 状态价值函数 v π ( s ) v_\pi(s) vπ​(s)是从状态 s s s出发&#xff0c;直至一幕结束后获得的回报的期望值 动作价值函数 q π ( s , a ) q_\pi(s,a) qπ​(s,a)是从状态 s s s出发&#xff0c;采取动作 a a a后&…

donet使用指定版本sdk

ps:来自微软官方方案,实测可行,就是在项目任意目录下在新建 global.json,并配置sdk版本 SDK 使用最新安装的版本 SDK 命令包括 dotnet new 和 dotnet run。 .NET CLI 必须为每个 dotnet 命令选择一个 SDK 版本。 即使在以下情况下&#xff0c;它也会默认使用计算机上安装的最新…

x-cmd install | Orbiton:极简至上的终端文本编辑器与轻量级 IDE

目录 核心特点安装适用场景优势 厌倦了臃肿复杂的 IDE&#xff1f;渴望一个轻巧、快速、专注的编码环境&#xff1f;Orbiton&#xff0c;一款极简主义的终端文本编辑器与轻量级 IDE&#xff0c;将带给你前所未有的编码体验。 核心特点 极简主义&#xff0c;专注编码&#xff1…

大脑、机器人与贝叶斯信念及AI推理

在机器不再局限于重复性任务的世界里&#xff0c;机器人技术已经大胆地迈入了感知、学习和决策的领域。这篇文章探讨了智能机器人系统是如何构建的——从理解它们嘈杂的传感器和不确定的环境&#xff0c;到使它们能够做出明智的选择并随着时间的推移调整自己的行为。 AI推理 …

线上婚恋相亲小程序源码介绍

​基于ThinkPHP、FastAdmin和UniApp开发的线上婚恋相亲小程序源码&#xff0c;这款小程序源码采用了ThinkPHP作为后端框架&#xff0c;其强大的功能与良好的扩展性为程序的稳定运行提供了保障。 ​FastAdmin作为后台管理框架&#xff0c;使得管理员能够便捷地对用户信息、相亲…

长短期记忆(LSTM)简介

RNN 的主要限制在于它无法记住很长的序列&#xff0c;并且会陷入梯度消失的问题。 什么是梯度消失问题&#xff1f; 当添加更多具有某些激活函数的层时&#xff0c;神经网络中损失函数的梯度趋近于零&#xff0c;这使得网络难以训练。 长短期记忆&#xff08;LSTM&#xff09;…

JESD204B 探究

JESD204B协议是高速串行接口标准,主要用于ADC/DAC与逻辑器件(如FPGA)之间的数据传输。以下为综合解析: 一、协议概述 ‌核心作用‌ 通过高速SERDES技术实现数模转换器与逻辑器件间的高效数据传输,支持多通道同步和确定性延迟,适用于GB级吞吐量场景23。‌版本演进‌ JESD2…

Flutter PIP 插件 ---- 新增PipActivity,Android 11以下支持自动进入PIP Mode

接上文 Flutter PIP 插件 ---- Android 项目地址 PIP&#xff0c; pub.dev也已经同步发布 pip 0.0.3&#xff0c;你的加星和点赞&#xff0c;将是我继续改进最大的动力 开发文档 Add videos using picture-in-picture (PiP)介绍PIP功能从 Android 8.0 (API level 26) 引入&…

【Java开发日记】6个Java 工具,轻松分析定位 JVM 问题 !

目录 使用 JDK 自带工具查看 JVM 情况 jps jinfo jvisualvm jcm 使用 JDK 自带工具查看 JVM 情况 JDK 自带了很多命令行甚至是图形界面工具&#xff0c;帮助查看 JVM 的一些信息。比如&#xff0c;在机器上运行 ls 命令&#xff0c;可以看到 JDK 8 提供了非常多的工具或程…

动态规划简单题2

leetcode91题&#xff08;解码方法&#xff09; 分析题目&#xff1a; 1.这是一种解码&#xff0c;就是给多个数字组成的字符串&#xff0c;把这些数字解码成字母&#xff0c;看看一共有多少种 2.如果一个数字前有前导0就不合法&#xff0c;比如06&#xff0c;这与6不同&…

(007)Excel 公式的使用

文章目录 逻辑运算公式的参数常用函数引用方式引用工作表和工作簿表格的引用修改公式的计算时机区域交叉引用 逻辑运算 公式的参数 单元格引用&#xff1a;SUM(A1:A24)。字面值&#xff1a;SQRT(121)。字面文本字符串&#xff1a;PROPER(“john.f.smith”)。表达式&#xff1a…

Unity 和 Unreal Engine(UE) 两大主流游戏引擎的核心使用方法

以下是 Unity 和 Unreal Engine&#xff08;UE&#xff09; 两大主流游戏引擎的核心使用方法和对比分析&#xff0c;帮助开发者快速上手并根据项目需求选择合适工具&#xff1a; 一、Unity 使用指南 1. 安装与配置 安装&#xff1a;从 Unity Hub 下载&#xff0c;选择长期支持…

猜数字游戏:从数学原理到交互体验的完整设计指南

目录 猜数字游戏&#xff1a;从数学原理到交互体验的完整设计指南引言第一章 游戏数学原理1.1 均匀分布与随机生成1.2 最优猜测策略 第二章 游戏系统设计2.1 核心架构2.2 动态难度系统 第三章 交互设计细节3.1 输入验证系统3.2 渐进式提示机制 第四章 进阶功能设计4.1 智能辅导…

2025工业大模型白皮书 | 蚂蚁工厂北京航空航天大学联合出品

由蚂蚁工厂与北京航空航天大学联合发布的《2025工业大模型白皮书》是一部针对工业领域大模型技术发展的前瞻性研究报告。该白皮书系统梳理了工业大模型的技术演进、核心应用场景、关键挑战及未来发展趋势&#xff0c;旨在为制造业数字化转型提供理论支撑和实践指南。作为产学研…

JavaWeb:后端web基础(TomcatServletHTTP)

一、今日内容 二、Tomcat 介绍与使用 介绍 基本使用 小结 配置 配置 查找进程 三、Servlet 什么是Servlet 快速入门 需求 步骤 1.新建工程-模块&#xff08;Maven&#xff09; 2.修改打包方式-war 3.编写代码 /*** 可以选择继承HttpServlet*/ WebServlet("/hello&q…

构建现代分布式云架构的三大支柱:服务化、Service Mesh 与 Serverless

目录 前言1. 服务化架构模式&#xff1a;构建可扩展的基础单元1.1 服务化的定义与演进1.2 在分布式云中的价值1.3 面临的挑战 2. Service Mesh 架构&#xff1a;服务通信的治理中枢2.1 什么是 Service Mesh&#xff1f;2.2 功能与优势2.3 在分布式云中的角色2.4 落地难点 3. Se…