数组类型
1. 什么是数组?
数组(Array)是 一组相同类型的数据的集合。如果我们有一组类型相同的变量,例如,5位同学的成绩,可以这么写:
1 2 3 4 5 6 7 8 9 10
| public class Main { public static void main(String[] args) { int n1 = 68; int n2 = 79; int n3 = 91; int n4 = 85; int n5 = 62; } }
|
但其实没有必要定义5个int变量。可以使用数组来表示“一组”int类型。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| public class Main { public static void main(String[] args) { int[] ns = new int[5]; ns[0] = 68; ns[1] = 79; ns[2] = 91; ns[3] = 85; ns[4] = 62; } }
|
2. 数组的定义与创建
数组类型写法:
示例:
数组的重要特性
- 数组元素自动初始化为默认值:
- int → 0
- double → 0.0
- boolean → false
- 引用类型 → null
- 数组长度固定,一旦创建不可改变
- 数组是引用类型
3. 访问数组元素(索引)
数组索引从 0 开始:
读取元素:
数组长度:
索引越界会报错:
数组索引永远 < nums.length
4. 数组的初始化方式
方式 1:先创建,再赋值
1 2 3
| int[] ns = new int[5]; ns[0] = 68; ...
|
方式 2:直接给初始值(编译器自动决定长度)
1
| int[] ns = new int[] { 68, 79, 91, 85, 62 };
|
还可以进一步简写为:
1
| int[] ns = { 68, 79, 91, 85, 62 };
|
5. 数组是引用类型
数组变量保存的不是内容,而是 指向数组对象的引用。
1 2
| int[] ns = new int[] { 1, 2, 3 }; ns = new int[] { 4, 5 };
|
此时:
- 新数组
{4, 5} 创建
- ns 改为指向新数组
- 原数组
{1,2,3} 仍存在,但 ns 不再引用它
数组内容本身 没有变,变的是变量 ns 的指向。
对于数组ns来说,执行ns = new int[] { 1,2,3 };时,它指向一个3个元素的数组:
1 2 3 4 5 6
| ns │ ▼ ┌───┬───┬───┬───┬───┬───┬ │ │1 │2 │3 │ │ │ └───┴───┴───┴───┴───┴───┴
|
执行ns = new int[] { 4,5 };时,它指向一个新的3个元素的数组:
1 2 3 4 5 6
| ns ──────────────────────┐ │ ▼ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬ │ │1 │2 │3 │ │ │ 4 │ 5 │ │ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴
|
但是,原有的3个元素的数组并没有改变,只是无法通过变量ns引用到它们而已。
6. 引用类型元素的数组
如果数组元素不是基本类型,而是一个引用类型,那么,修改数组元素会有哪些不同?
字符串是引用类型,因此我们先定义一个字符串数组:
1
| String[] names = {"ABC", "XYZ", "zoo"};
|
对于String[]类型的数组变量names,它实际上包含3个元素,但每个元素都指向某个字符串对象:
1 2 3 4 5 6 7 8 9
| ┌─────────────────────────┐ names │ ┌─────────────────────┼───────────┐ │ │ │ │ │ ▼ │ │ ▼ ▼ ┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┐ │ │░░░│░░░│░░░│ │ "ABC" │ │ "XYZ" │ │ "zoo" │ │ └───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┘ │ ▲ └─────────────────┘
|
对names[1]进行赋值,例如names[1] = "cat";,效果如下:
1 2 3 4 5 6 7 8 9
| ┌─────────────────────────────────────────────────┐ names │ ┌─────────────────────────────────┐ │ │ │ │ │ │ ▼ │ │ ▼ ▼ ┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┬───────┬───┐ │ │░░░│░░░│░░░│ │ "ABC" │ │ "XYZ" │ │ "zoo" │ │ "cat" │ │ └───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┴───────┴───┘ │ ▲ └─────────────────┘
|
这里注意到原来names[1]指向的字符串"XYZ"并没有改变,仅仅是将names[1]的引用从指向"XYZ"改成了指向"cat",其结果是字符串"XYZ"再也无法通过names[1]访问到了。
7. 思考题解析
对“指向”有了更深入的理解后,试解释如下代码:
1 2 3 4 5 6 7 8 9
| public class Main { public static void main(String[] args) { String[] names = {"ABC", "XYZ", "zoo"}; String s = names[1]; names[1] = "cat"; System.out.println(s); } }
|
输出是什么?
答案:XYZ
原因:
s = names[1] 时,s 指向 "XYZ"
- 后来
names[1] = "cat"
只改变了 names[1] 的指向
并没有改变 "XYZ" 本身
- s 仍然指向
"XYZ"
8. 小结
- 数组是一组相同类型的数据。
- 数组是引用类型,变量指向数组对象。
- 数组一旦创建长度固定。
- 访问数组要用索引(0 ~ length-1),越界会报错。
- 数组元素可以是基本类型,也可以是引用类型。