11.数组进阶


一、数组原理内存图

1、内存概述

内存是计算机中的重要原件,临时存储区域,作用是运行程序,我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放在内存中才能运行,运行完毕后会清空内存。

Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。

2、Java虚拟机的内存划分

为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

  • JVM的内存划分
区域名称 作用
寄存器 给CPU使用,和开发无关
本体方法栈 JVM在使用操作系统功能的时候使用,和我们开发无关
方法区 存储可以运行的.class 文件
堆内存 存储对象或数组,new来创建的,都存储在堆内存
方法栈 方法运行时使用的内存,比如main方法运行,进入方法栈中执行

3、数组在内存中的存储

(1)、一个数组内存图

public static void main(String[] args){
    int[] arr = new int[3];
    System.out.println(arr); //[I@7c30a502
}

以上方法执行,输出的结果是[I@7c30a502,这个是什么?是数组在内存中的地址,new出来的内容,都在堆内存中存储,二方法中的arr保存的是数组的地址。

输出arr[0],就会输出arr保存的内存地址中数组索引为0的元素。

程序执行流程:

  • 1、main方法进入方法栈执行
  • 2、创建数组,JVM会在堆内存中开辟空间,存储数组
  • 3、数组在内存中会有自己的内存地址,以十六进制数表示
  • 4、数组中有3个元素,默认值为0
  • 5、JVM将数组的内存地址赋值给引用类型变量arr
  • 6、变量arr保存的是数组内存中的地址,而不是一个具体数值,因此称为引用数据类型

1_Java_Memory

(2)、两个数组内存图

public static void main(String[] args){
    int[] arr1 = new int[3];
    int[] arr2 = new int[2];
    System.out.println(arr1);
    System.out.println(arr2);
}

2_Java_Memory

(3)、两个变量指向一个数组

public static void main(String[] args){
    // 定义数组。存储3个元素
    int[] arr = new int[3];
    // 数组索引进行赋值
    arr[0] = 5;
    arr[1] = 6;
    arr[2] = 7;
    // 输出元素值
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);
    // 定义数组变量arr2,将arr的地址赋值arr2
    int[] arr2 = arr;
    arr2[1] = 9;
    System.out.println(arr[1]);
}

3_Java_Memory

(4)、举例

4_Java

二、数组的常见操作

1、数组越界异常

看下面代码:

public static void main(String[] args){
    int[] arr = {1, 2, 3};
    System.out.println(arr[3]);
}

创建数组,赋值3个元素,数组的索引就是0, 1, 2,没有索引3,因此我们不能访问数组中不存在的索引,程序运行后,将会抛出ArrayIndexOutOfBoundsException数组越界异常。在开发中,数组的越界异常是不能出现的,一旦出现,就需要修改代码。

2、数组空指针异常

观察以下代码,运行后会出现什么结果。

public static void main(String[] args){
    int[] arr = {1, 2, 3};
    arr = null;
    System.out.println(arr[0]);
}

arr = null这行代码,意味着变量arr将不会保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出NullPointerException空指针异常。在开发中,数组的越界异常是不能出现的,一旦出现,就必须修改代码。

空指针在内存图中的表现

5_Java_NullPointer

3、数组遍历【重点】

  • 数组遍历:就是将数组中的每个元素都分别获取出来,就是遍历。遍历也是数组操作中的基石。
public static void main(String[] args){
    int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
    arr.length.
}

4、数组获取最大值元素

  • 最大值获取:从数组的所有元素中找出最大值
  • 实现思路:
    • 定义变量,保存数组索引0的元素A
    • 遍历数组,获取出数组中的每个元素
    • 将遍历到的元素和保存数组A进行比较
    • 如果数组元素A的值大于遍历的元素值,就将A记为最大值,否则将遍历的值记为最大值
    • 数组循环遍历结束,得到最大值
public static void main(String[] args) {
        int[] arr = {5, 15, 30, 20, 1000};

        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i] > max){
                max = arr[i];
            }
        }
        System.out.println(max);
    }

5、数组反转

  • 数组反转:数组中的元素颠倒顺序
  • 实现思路:数组最远端的元素互换位置(要求原地反转)
public static void arrayReverseReplace(int[] arr){
    int i = 0;
    int j = arr.length - 1;
    int temp;

    while(i < j){
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        i++;
        j--;
    }
}

三、数组作为方法参数和返回值

1、数组作为方法参数

以前的方法中学习了方法的参数和返回值,但是使用的都是基本数据类型,那么作为引用类型的数组能够作为方法的参数进行传递呢?当然可以!

  • 数组作为方法参数传递,传递的参数都是数组内存的地址
public static void main(String[] args){
    int[] arr = {1, 3, 5, 7, 9};
    //调用方法,传递数组
    printArray(arr);
}

public static void printArray(int[] arr){
    for(int i = 0; i < arr.length; i++){
        System.out.println(arr[i]);
    }
}

2、数组作为方法返回值

  • 数组作为方法的返回值,返回的是数组的内存地址
  • 一个方法可以有0、1、或多个参数,但是只能有0或1个返回值,不能有多个返回值, 如果希望一个方法当中产生多个结果的返回值,可以使用一个数组作为返回值类型即可
public static void main(String[] args){
    //调用方法,接收数组的返回值
    //接受到的是数组的内存地址
    int[] arr = getArray();
    for (int i = 0; i < arr.length, i++){
        System.out.println(arr[i]);
    }
}

public static int[] getArray(){
    int[] arr = {1, 3, 4, 5, 6};
    return arr;
}
public static void main(String[] args) {
    int[] result = calculate(10, 20);
    System.out.println("总和为:" + result[0]);
    System.out.println("平均数:" + result[1]);
}

public static int[] calculate(int a, int b){
    int sum = a + b;
    int avg = sum / 3;
    int[] res = {sum, avg};
    return res;
}

总结:方法的参数为基本类型时,传递的是数据值,方法的参数为引用类型时,传递的是地址值.


Author: Wolfwotz
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Wolfwotz !
  TOC