数组(Java基础语法)

数组的声明

语法拆解:int[] scores;

我们把这句代码分成三个部分来看:

1. int (元素类型 - Type)
  • 含义 : 这部分指定了未来这个数组中,每一个"格子"里存放的数据的类型

  • int 表示这个数组是一个"整型数组",它里面的每个元素都必须是 int 类型的整数。

  • 你也可以声明其他类型的数组:

    • double[] prices; (一个用来装 double 类型价格的数组)

    • String[] names; (一个用来装 String 类型名字的数组)

    • char[] letters; (一个用来装 char 类型字母的数组)

  • 规则 : 一个数组一旦被声明为某种类型,它就永远只能存放该类型的数据,不能混装。

2. [] (数组标识符)
  • 含义 : 这对方括号 [] 是语法的核心,它告诉编译器:"这不是一个普通的 int 变量,而是一个能装很多个 int 的数组!"

  • 它就像给变量贴上了一个"容器"的标签。

  • int scores; -> 只能装 一个 int。

  • int[] scores; -> 能装 一串 int。

  • 写法的灵活性:

    • int[] scores; ( 推荐的写法,类型 int[] 和变量名 scores 分离,更清晰)

    • int scores[]; ( C/C++风格的写法,Java为了兼容也支持,但不推荐)

    • 这两种写法在功能上完全等价,但社区和官方更推荐第一种,因为它更符合Java的"类型 变量名"的声明风格。

3. scores (变量名 - Identifier)
  • 含义 : 这是我们给这个"数组引用变量"起的名字。

  • 以后,我们就可以通过 scores 这个名字,来访问和操作这个数组了。

  • 变量名需要遵循Java的标识符命名规范(比如不能以数字开头,不能是关键字等),通常使用有意义的小驼峰命名法


数组的初始化

哪种情况用哪个?

|-----------|-----------------|------------|-----------------|
| 初始化方式 | 决策依据 | 核心思想 | 例子 |
| 动态初始化 | 只知道长度,不知道内容 | "先占坑,后填数" | 用户输入、存放计算结果 |
| 静态初始化 | 已经知道确切内容 | "坑和数,一步到位" | 星期、月份、固定配置、测试数据 |

1. 静态初始化 (Static Initialization)

"内容驱动"的初始化

  • 核心思想 : 在创建数组的同时 ,就直接指定 数组中要存放的具体元素内容。数组的长度 由你提供元素的个数自动决定

  • 适用场景 : 当你已经明确知道数组里应该放哪些具体的值时,就用静态初始化。

  • 口诀 : "内容决定长度"

完整语法:
复制代码
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, ...};

示例:

复制代码
int[] arr = new int[]{1, 2, 3, 4, 5};
String[] names = new String[]{"张三", "李四", "王五"};
简化语法 (更常用):
复制代码
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};

2. 动态初始化 (Dynamic Initialization)

"长度驱动"的初始化

  • 核心思想 : 在创建数组时,只指定数组的长度 ,而不关心里面元素的具体内容。数组中每个元素的初始值,会由系统根据其数据类型自动分配一个默认值

  • 适用场景 : 当你只知道需要多大的空间,但具体的值要在程序运行过程中,再慢慢填充进去时,就用动态初始化。

  • 口诀 : "长度决定内容"

语法:
复制代码
数据类型[] 数组名 = new 数据类型[数组长度];

示例:

java 复制代码
// 创建一个能存放5个整数的数组,所有位置的初始值都是 0
int[] numbers = new int[5]; 

// 创建一个能存放10个字符串的数组,所有位置的初始值都是 null
String[] userList = new String[10];

动态初始化之后,数组里填的都是默认值(int 就是 0)。给它填上我们想要的数,其实非常简单,核心就一步:通过索引定位,然后赋值

方式一:手动一个一个地填(最基础,但不常用)

这就像你手动操作:

  1. 找到第1个格子(索引是0),把里面的 0 换成 10。

  2. 找到第2个格子(索引是1),把里面的 0 换成 20。

  3. 找到第3个格子(索引是2),把里面的 0 换成 30。

对应的代码:

复制代码
int[] array2 = new int[3]; // 此时内容是 {0, 0, 0}

// 开始填数
array2[0] = 10; // 把 10 赋值给索引为 0 的位置
array2[1] = 20; // 把 20 赋值给索引为 1 的位置
array2[2] = 30; // 把 30 赋值给索引为 2 的位置

// 现在,array2 的内容就变成了 {10, 20, 30}
System.out.println(array2[0]); // 输出 10
System.out.println(array2[1]); // 输出 20
System.out.println(array2[2]); // 输出 30

缺点:如果数组有100个元素,你总不能写100行代码吧?太笨拙了!所以我们需要更聪明的方法。


方式二:使用 for 循环来填(最常用,最高效)

这才是我们处理数组的标准方法。循环可以自动地、重复地帮我们完成"定位 -> 赋值"这个操作。

核心思路:

让循环变量 i 从 0 开始,每次循环都作为数组的索引,直到遍历完所有位置。

一个完整的例子:从键盘输入5个学生的成绩

复制代码
import java.util.Scanner;

public class FillArrayExample {
    public static void main(String[] args) {
        // 1. 动态初始化:创建一个能装5个分数的数组,现在全是0
        int[] scores = new int[5];
        
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入5位学生的成绩:");

        // 2. 使用 for 循环填数
        // scores.length 的值是 5
        // 循环会执行5次,i 的值会依次是 0, 1, 2, 3, 4
        for (int i = 0; i < scores.length; i++) {
            System.out.print("请输入第 " + (i + 1) + " 位学生的成绩: ");
            // 关键代码在这里!
            // 第一次循环 (i=0): scores[0] = 用户输入的值
            // 第二次循环 (i=1): scores[1] = 用户输入的值
            // ...以此类推
            scores[i] = sc.nextInt(); 
        }

        System.out.println("--------------------");
        System.out.println("所有学生的成绩录入完毕,如下:");

        // 3. 使用另一个 for 循环来查看结果
        for (int i = 0; i < scores.length; i++) {
            System.out.println("第 " + (i + 1) + " 位学生的成绩是: " + scores[i]);
        }
    }
}
运行这个程序,你会看到:
复制代码
请输入5位学生的成绩:
请输入第 1 位学生的成绩: 98
请输入第 2 位学生的成绩: 85
请输入第 3 位学生的成绩: 77
请输入第 4 位学生的成绩: 92
请输入第 5 位学生的成绩: 100
--------------------
所有学生的成绩录入完毕,如下:
第 1 位学生的成绩是: 98
第 2 位学生的成绩是: 85
第 3 位学生的成绩是: 77
第 4 位学生的成绩是: 92
第 5 位学生的成绩是: 100

数组的访问

"访问"数组,主要包含两个动作:

  1. 读取数组中某个位置的元素值。

  2. 修改数组中某个位置的元素值。

这两个动作都依赖于同一个关键概念------索引 (Index)

1. 核心概念:索引 (Index)

你可以把数组想象成电影院里的一排座位,或者一栋楼里的一个个房间。

  • 数组: 就是那一整排座位。

  • 元素: 就是每个座位上坐着的人。

  • 索引 : 就是每个座位的编号

索引有两条铁律,必须牢记:

  1. 索引从 0 开始

    • 第一个元素的索引是 0,第二个是 1,第三个是 2,以此类推。

    • 这是一个非常非常重要的计算机编程约定,几乎所有主流语言都遵循这个规则。

  2. 最大索引是 数组长度 - 1:

    • 如果一个数组有 5 个元素(长度为5),那么它的索引范围就是 0, 1, 2, 3, 4。最大索引是 5 - 1 = 4。

    • 如果你试图访问超出这个范围的索引(比如 -1 或者 5),程序就会立刻崩溃,并抛出著名的 ArrayIndexOutOfBoundsException (数组索引越界异常)。

2. 访问数组的语法

访问数组的语法非常简单,就是:

数组名[索引]

这个语法既可以用来读取 ,也可以用来修改

代码示例:

我们先创建一个数组,作为操作的对象:

复制代码
// 创建一个长度为 5 的整型数组,用来存放考试成绩
int[] scores = {95, 88, 76, 99, 82};

现在,这个 scores 数组在内存中的样子是:

|--------|-------|-------|-------|-------|-------|
| 元素值 | 95 | 88 | 76 | 99 | 82 |
| 索引 | 0 | 1 | 2 | 3 | 4 |


3. 读取元素 (Reading Elements)

把 数组名[索引] 这个表达式放在等号的右边,或者直接用在打印语句里,就是读取操作。

复制代码
public class ArrayRead {
    public static void main(String[] args) {
        int[] scores = {95, 88, 76, 99, 82};

        // 读取第一个元素 (索引为 0)
        int firstScore = scores[0];
        System.out.println("第一个学生的成绩是: " + firstScore); // 输出: 95

        // 读取第三个元素 (索引为 2)
        int thirdScore = scores[2];
        System.out.println("第三个学生的成绩是: " + thirdScore); // 输出: 76

        // 读取最后一个元素 (索引为 长度-1)
        // scores.length 的值是 5
        int lastScore = scores[scores.length - 1]; // scores[4]
        System.out.println("最后一个学生的成绩是: " + lastScore); // 输出: 82

        // 错误示例:访问不存在的索引
        // int errorScore = scores[5]; // 这行代码会立刻让程序崩溃!
    }
}

4. 修改元素 (Modifying Elements)

把 数组名[索引] 这个表达式放在等号的左边,就是修改操作(也叫赋值)。

复制代码
public class ArrayModify {
    public static void main(String[] args) {
        int[] scores = {95, 88, 76, 99, 82};

        // 打印修改前的第二个成绩
        System.out.println("修改前,第二个学生的成绩是: " + scores[1]); // 输出: 88

        // 修改第二个元素的值 (索引为 1)
        // 把 90 这个值,存放到索引为 1 的位置上
        scores[1] = 90;

        // 打印修改后的第二个成绩
        System.out.println("修改后,第二个学生的成绩是: " + scores[1]); // 输出: 90
        
        // --- --- ---

        // 假设第四个学生 (索引为 3) 的成绩录错了,应该是满分
        scores[3] = 100;
        System.out.println("订正后,第四个学生的成绩是: " + scores[3]); // 输出: 100
    }
}

数组的属性

length 是数组一个非常重要的内置属性,它简单、直接,但又极其有用。


1. 核心概念:length 是什么?

  • 定义 : length 是每个数组对象都自带 的一个属性 ,它表示这个数组可以容纳的元素总数

  • 直观理解 : 它就是数组的"长度"或者"容量"。

  • 语法: 数组名.length

  • 返回值: 一个 int 类型的整数。

重要特性:

  1. 它是属性,不是方法 : 注意 length 后面没有括号 ()

    • scores.length (✔︎ 正确)

    • scores.length() (❌ 错误! 这会让编译器以为你在调用一个叫 length 的方法)

    • (这与字符串的 length() 方法不同,是初学者容易混淆的地方)

  2. 它是 final 的 (只读) : 一旦数组被创建,它的长度就固定不变 了。你只能读取 length 属性的值,不能修改它。

    • int len = scores.length; (✔︎ 正确)

    • scores.length = 10; (❌ 错误! 无法为最终变量length分配值)


2. length 的作用和用法

length 属性最核心的用途,就是让我们的代码能够"知道"数组有多长,从而进行安全、灵活的操作。它主要用在以下两个关键场景:

场景一:获取数组的长度信息

这是最直接的用法。

代码示例:

codeJava

复制代码
public class ArrayLengthDemo {
    public static void main(String[] args) {
        // 静态初始化的数组
        String[] fruits = {"Apple", "Banana", "Orange"};
        int fruitCount = fruits.length;
        System.out.println("水果数组的长度是: " + fruitCount); // 输出: 3

        // 动态初始化的数组
        int[] numbers = new int[10]; // 创建一个长度为10的数组
        int numberCapacity = numbers.length;
        System.out.println("数字数组的长度是: " + numberCapacity); // 输出: 10

        // 空数组
        double[] emptyArray = {};
        System.out.println("空数组的长度是: " + emptyArray.length); // 输出: 0
    }
}
场景二:数组的遍历 (最重要的用途!)

遍历 (Traversal) ,就是从头到尾访问数组中的每一个元素。如果我们不知道数组有多长,就无法做到这一点。length 属性是实现数组遍历的关键

问题: 如何打印出 scores 数组中的每一个成绩?

错误的方式 (硬编码):

复制代码
int[] scores = {95, 88, 76, 99, 82};
System.out.println(scores[0]);
System.out.println(scores[1]);
System.out.println(scores[2]);
System.out.println(scores[3]);
System.out.println(scores[4]);

这种写法非常笨拙,如果数组有100个元素,你就要写100行。而且如果数组长度变了,代码就得重写。

正确的方式 (使用 for 循环和 .length):

复制代码
public class ArrayTraversal {
    public static void main(String[] args) {
        int[] scores = {95, 88, 76, 99, 82, 100, 75}; // 我们可以随时增删元素

        System.out.println("数组 scores 的长度是: " + scores.length); // 输出: 7

        // 使用 for 循环遍历数组
        // i 的范围是从 0 到 scores.length - 1
        for (int i = 0; i < scores.length; i++) {
            // 在循环中,i 的值会依次是 0, 1, 2, 3, 4, 5, 6
            System.out.println("索引为 " + i + " 的元素是: " + scores[i]);
        }
    }
}

输出:

复制代码
数组 scores 的长度是: 7
索引为 0 的元素是: 95
索引为 1 的元素是: 88
索引为 2 的元素是: 76
索引为 3 的元素是: 99
索引为 4 的元素是: 82
索引为 5 的元素是: 100
索引为 6 的元素是: 75

为什么这种方式好?

  1. 自动化: 循环会自动处理从第一个到最后一个的所有元素。

  2. 灵活性/自适应 : 无论 scores 数组的长度变成多少(5个、10个、100个),这段遍历代码完全不需要修改 ,因为它总是通过 scores.length 来动态获取正确的循环次数。这让我们的代码非常健壮

  3. 安全性 : i < scores.length 这个条件,完美地保证了索引 i 的最大值只会是 scores.length - 1,从而杜绝了数组越界的风险

相关推荐
Kiri霧4 小时前
Rust开发环境搭建
开发语言·后端·rust
weixin-a153003083164 小时前
[数据抓取-1]beautifulsoup
开发语言·python·beautifulsoup
遇印记4 小时前
大二java学习笔记:二维数组
java·笔记·学习
小杨同学yx5 小时前
有关maven的一些知识点
java·开发语言
小韩博5 小时前
IDEA的简单使用
java·ide·intellij-idea
我是华为OD~HR~栗栗呀5 小时前
华为od-21届考研-C++面经
java·c语言·c++·python·华为od·华为·面试
埃泽漫笔5 小时前
RabbitMQ 核心概念解析
java·mq
oioihoii5 小时前
C++ 中的类型转换:深入理解 static_cast 与 C风格转换的本质区别
java·c语言·c++
重生之我要当java大帝5 小时前
java微服务-尚医通-编写医院设置接口下
java·开发语言·sql
寻找华年的锦瑟5 小时前
Qt-QDir
开发语言·qt