数组
数组的定义
java
int[] a = {0, 1, 2};提示:Java 中,数组定义时, [ ] 写在数据类型后(更规范),当然也可以写在变量名后
基本介绍
(1)数组的下标从 0 开始编号(第一个元素的下标)
(2)元素下标索引 = 元素物理位置 - 1
(3)数组的本质:数组的类型是引用类型,底层是一个指针
补充:Java 中的引用数据类型:数组,类,接口
数组的底层存储机制
基本介绍
jvm 的内存
_____________ ——————————————————————————————
| | | 堆空间
| | |
| 栈空间 | |
| | |______________________________
| | | 方法区
—————————————— |______________________________(1)定义一个数组( int [ ] a ),此时数组默认指向 null,数组初始化时,jvm 内存发生变化,在堆空间中分配内存给数组,同时会返回一个地址
(2)int [ ] a = new int [ 5 ],数组初始化完成,每一段内存空间对应一个空间地址(起始地址),此时 a 会引用内存空间的地址
值传递
底层实现:先把 a 的值拷贝一份,然后赋值给 b,两个值之间不会相互影响
java
int a = 10;
int b = a;引用传递
底层实现:传递的内容是一个地址,即地址的引用发生变化,把 b 赋给 a 就表示 b 指向了 a 的引用(即 b 指向了 a 指向的内存空间),此时操作数组 b 等同于操作数组 a
java
int[] a = {1, 2, 3};
int[] b = a;
b[0] = 10;数组的初始化
静态初始化
java
int[] a = {1, 2, 3};动态初始化
使用关键字 new。初始化时需要指定数组的类型和空间大小
举例:int [ ] a = new int [ 5 ]
方式一:直接使用动态分配
java
double scores[] = new double[5];方式二:先声明,后分配
java
double scores[]; // 此时 scores 是 null
scores = new double[5];结合 scanner 录入数组值
获取数组长度:数组名 . length( )
java
import java.util.Scanner;
public class Main{
public static void main(String[] args){
// 创建扫描器
Scanner scanner = new Scanner(System.in);
int[] a = new int[5];
// 动态录入
for( int i = 0; i < a.length; i++){
a[i] = scanner.nextInt();
}
// 打印测试
for( int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}
}
}使用细节
(1)数组在初始化是就指定了类型,元素的数据类型需要相同,不可以混用
错误案例
int [ ] a = { 1, 2, 3.5 };
错因分析:不可以把一个 double 赋值给 int
(2)数组定义后,如果没有初始化,会有默认值
int: 0
short: 0
byte: 0
long: 0
float: 0.0
double: 0.0
char: \u0000
boolean: false
String:null
(3) 数组的下标是从 0 开始的,元素下标索引 = 元素物理位置 - 1,警惕下标索引越界
java
int[] arr = new int[5]; // 有效下标为 0 - 4数组拷贝
注意:区别于数组的地址传递,数组拷贝后两个数组独立,互不影响
思路分析
(1)首先创建一个新的数组,空间大小和原数组一致
(2)for 遍历原数组,把原数组中的每一个值赋给新数组
(3)打印新数组的值测试
代码示例
java
int[] a ={1, 2, 3};
int[] b = new int[a.length];
// 数组拷贝
for( int i = 0; i < a.length; i++){
b[i] = a[i];
}
System.out.print("a数组的值:");
for( int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}
System.out.println("");
System.out.print("b数组的值:");
for( int i = 0; i < b.length; i++){
System.out.print(b[i] + " ");
}
// 输出结果
a数组的值:1 2 3
b数组的值:1 2 3翻转数组
逆序赋值
创建一个新数组 b,逆序拷贝数组 a,修改引用,让 a 指向 b 的引用,利用 Java 中的垃圾回收机制,自动回收数组 a,此时 a、b 指向同一个内存地址
java
int[] a = {1, 2, 3};
int[] b = new int[a.length];
for( int i = a.length()-1,j = 0; i >= 0; i--,j++){
b[j] = a[i];
}
a = b; //让 a 指向 b
for( int i = 0; i < b.lengt; i++){
System.out.print(b[i] + " ");
}
System.out.println("");
for( int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}双指针法
建立头指针,尾指针,两指针相向而行(相撞指针),过程中交换两个指针指向的值,当两指针在中点相遇时,循环结束
java
int[] a = {1, 2, 3};
for( int i = 0,j = a.length-1; i < a.length / 2; i++,j--){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
for( int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}
//输出: 3 2 1