Skip to content

数组


数组的定义

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