5. Java中的数组以及多维数组


一、数组简介

概念:是一种容器,可以同时存放多个数据值。

数组的特点

  1. 数组是一种引用数据类型
  2. 数组当中的多个数据,类型必须统一(或者是当前类型的子类,例如:Object[]可以存放任意的数组类型,因为java中所有的类都是Object的子类)
  3. 数组的长度在程序运行期间不可改变。
  4. 数组的索引是从0开始的,一直到n-1(这个数组的长度为n);
  5. 数组一旦在内存中创建(不仅创建了储存数组地址的变量,而且还要向系统要到固定长度的空间地址)了,长度就无法改变了!

数组的初始化

  • 一、动态初始化(指定长度):
    基本格式:数据类型[] 数组名称 = new 数据类型[数组长度];
class Test {
    public static void main(String[] args){
        /**一步到位@*@*@*@ 推荐写法 @*@*@*@*/
        int[] array1 = new int[10];
        
        /**分开写*/
        int[] array2;
        array2 = new int[10];
        
        /**错误的写法
        int[] array3;
        array3 = {1, 2, 3, 4};
        */
    }
}

注意:使用动态数组初始化数组的时候,其中的元素会有一个默认值,

初始化数据类型 整型:byte、short、int、long 浮点数:double、float 字符:char boolean:true、false 引用类型(对象)
默认值 0 0.0 '\u0000' false null
  • 二、静态初始化(指定内容):
    基本格式:数据类型[] 数组名称 = new 数据类型[] {item1, item2, ...};

提示:虽然静态初始化没有直接告诉长度,但是根据大括号里面的元素具体内容推算出数组的长度,这个是JVM底层的优化。

class Test {
    public static void main(String[] args){
        /**一步到位*/
        int[] array1 = new int[]{1, 2, 3, 4, 5};
        
        /**一步到位的简写形式@*@*@*@ 推荐写法 @*@*@*@**/
        int[] array2 = {1, 2, 4, 5, 6};
        
        /**分开写*/
        int[] array3;
        array3 = new int[]{1, 2, 3, 4, 5};
        
        /**错误的写法如下:
        int[] array4;
        array4 = {1, 2, 4, 5, 6};
        */
    }
}

注意:直接打印数组的名称,得到的结果是数组类型与内存地址哈希值的拼接(其实在源码中,这个功能是在toString()这个方法中定义的,打印一个对象名,实际就是调用的这个方法,可以对这个方法进行多态操作,实现自己想要的效果)

二、以一维数组为例深入理解数组的引用(地址)

Java的内存划分

Java的内存划分主要分为5,个部分--> 栈(Stack)、堆(Heap)、方法区(Method Area)、本地方法查找栈(Native Method Stack)、寄存器(pc Register);一个class文件执行的大致过程是 (提醒:这只是逻辑上的执行,这层逻辑封装了底层操作系统的具体调用以及具体的物理电路逻辑):JVM将.class字节码文件加载方法区(就是一堆字符串),然后解析,将方法压入栈中 (这个方法区有其他的数据结构保存当前变量以及变量值,我猜是HashMap这种数据结构,如果错误请指出)在执行中如果由遇到方法2,则将方法2压入的栈中,直到这个方法执行完了,然后又把之前的方法出栈继续执行。如果遇到new操作,则在另一个叫做内存区(堆这种数据结构)中创建并入堆一个对象,并将地址赋值给相关的变量。


01-Java中的内存划分.png

1. 一个数组从创建到操作经历了哪些事?


02-只有一个数组的内存图.png

2. 两个同的数组


03-有两个独立数组的内存图.png

3. 两个变量指向同一个数组


04-两个引用指向同一个数组的内存图.png

必须深入理解数组的引用,变量中储存的是数组对应的内存地址,如果对数组变量进行赋值操作,比如有个数组int[] a = new int[3]; a = new int[]{1,2,3,4},对于这种情况,变量a指向一个新的长度为4的数组!

操作数组的一些注意事项:

  1. 数组的索引编号从0开始,一直到“数组的长度-1”为止。如果访问索引编号并不存在,抛出越界异常ArrayIndexOutOfBoundsException

  2. 所有的引用类型变量,都可以赋值为一个null值。但是代表其中什么都没有。数组必须进行new初始化才能使用其中的元素。如果只是赋值了一个null,没有进行new创建,那么将会发生:空指针异常 NullPointerException

  3. 如何获取数组的长度,格式:数组名称.length

  4. 数组可以作为方法的参数。当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值。

  5. 一个方法可以有0、1、多个参数;但是只能有0或者1个返回值,不能有多个返回值。如果希望一个方法当中产生了多个结果数据进行返回,怎么办?解决方案:使用一个数组作为返回值类型即可。任何数据类型都能作为方法的参数类型,或者返回值类型。数组作为方法的参数,传递进去的其实是数组的地址值。数组作为方法的返回值,返回的其实也是数组的地址值。

三、二维数组

二维数组,顾名思义,就是一个数组中的元素也是一个数组,二维数组的第一层索引一定是一个对应数据类型的引用(一维的数组的引用),第二个索引可能是个引用也可能是个基本数据类型

二维数组的定义方式与使用方法

public class Test {

    public static void main(String[] args) {

        /**一、动态初始化(指定长度)*/
        int[][] array1 = new int[2][2];// @*@*@*@*@ 推荐方式1 @*@*@*@*@

        int[][] array2 = new int[][]{{1,2,3}, {2,3,4}};
        int[][] array3 = {{1,2,3},{5,6,7}};// @*@*@*@*@ 推荐方式2 @*@*@*@*@

        int[][] array4;
        array4= new int[][]{{1,4,5},{4,5,6}};
        
        
        /**二、静态初始化(不指定长度),第一层索引必须制定*/
        int[][] array5 = new int[5][];
        
        int[][] array6;
        array6 = new int[5][];
        
    }

}

我利用二维数组举了一个实际问题的栗子,有点难度哦!

黑马中学高三二班进行了一个期中考试,有一个5人小分队,他们的成绩如下score,对应的课程为subjects;对应的名字为studentsName;请计算出并输出①这5个同学的各自的最高分?②每一位同学的平均成绩?③每一科的最高分?④每一科的平均分?

public class Test {

    public static void main(String[] args) {
        double[][] score = {
                {110, 120, 110, 80, 69, 59},
                {97, 130, 120, 80, 65, 60},
                {107, 145, 119, 80, 64, 55},
                {99, 150, 130, 80, 66, 52},
                {112, 150, 99, 80, 68, 56}
        };
        String[] subjects = {"语文", "数学", "英语", "物理", "生物", "化学"};
        String[] studentsName = {"李逍遥", "梅长苏", "景天", "蒙毅", "宁采臣"};
        statisticsScore(score, subjects, studentsName);
    }

    public static void statisticsScore(double[][] score, String[] subjects, String[] studentsName) {

        // 记录每一位同学的最高分
        double[] highScoreStudent = new double[score.length];

        // 记录每一位同学的平均成绩
        double[] averageScoreStudent = new double[score.length];

        // 记录每一科的最高分
        double[] hightScoreSubject = new double[score[0].length];

        // 记录每一科的平均分
        double[] averageScoreSubject = new double[score[0].length];

        // 计算每一位学生的信息----->横向遍历
        for(int i = 0; i < score.length; i ++) {

            double sumScoreStu = 0; // 累计当前同学的总分

            for(int j = 0; j < score[i].length; j ++) {
                // 记录当前同学的最高分
                if(score[i][j] > highScoreStudent[i])
                    highScoreStudent[i] = score[i][j];

                // 累计总分
                sumScoreStu += score[i][j];
            }
            // 计算并记录当前同学的平均分
            averageScoreStudent[i] = sumScoreStu / score[i].length;
        }

        // 计算每一门学科的信息----->纵向遍历
        for(int i = 0; i < score[0].length; i ++) {

            double sumScoreSub = 0; // 累计当前学科的总分

            for(int j = 0; j < score.length; j ++) {
                if(score[j][i] > hightScoreSubject[i])
                    hightScoreSubject[i] = score[j][i];
                sumScoreSub += score[j][i];
            }

            averageScoreSubject[i] = sumScoreSub / score.length;
        }

        printMsg(subjects, studentsName, highScoreStudent, averageScoreStudent,
                hightScoreSubject, averageScoreSubject);

    }

    public static void printMsg(String[] subjects,              // 学科名称
                                String[] studentsName,          // 同学姓名
                                double[] highScoreStudent,      // 同学最高成绩
                                double[] averageScoreStudent,   // 同学平均成绩
                                double[] hightScoreSubject,     // 学科最高分
                                double[] averageScoreSubject) { // 学科平均分

        System.out.println("*************************** 每一位同学的信息 ***************************");
        System.out.println("---------------------------------------------------------------------");
        System.out.print("| 学生姓名 | ");
        for(int i = 0; i < studentsName.length; i ++) {
            System.out.printf("%5s\t | ", studentsName[i]);
        }
        System.out.println();
        System.out.println("---------------------------------------------------------------------");
        System.out.print("| 最高成绩 | ");
        for(int i = 0; i < highScoreStudent.length; i ++) {
            System.out.printf("%5.2f\t | ", highScoreStudent[i]);
        }
        System.out.println();
        System.out.println("---------------------------------------------------------------------");
        System.out.print("| 平均成绩 | ");
        for(int i = 0; i < averageScoreStudent.length; i ++) {
            System.out.printf("%5.2f\t | ", averageScoreStudent[i]);
        }
        System.out.println();
        System.out.println("---------------------------------------------------------------------");

        System.out.println();

        System.out.println("*************************** 每一个学科的信息 ***************************");
        System.out.println("--------------------------------------------------------------------------------");
        System.out.print("| 学科名称 | ");
        for(int i = 0; i < subjects.length; i ++) {
            System.out.printf("%5s\t | ", subjects[i]);
        }
        System.out.println();
        System.out.println("--------------------------------------------------------------------------------");
        System.out.print("| 最高成绩 | ");
        for(int i = 0; i < hightScoreSubject.length; i ++) {
            System.out.printf("%5.2f\t | ", hightScoreSubject[i]);
        }
        System.out.println();
        System.out.println("--------------------------------------------------------------------------------");
        System.out.print("| 平均成绩 | ");
        for(int i = 0; i < averageScoreSubject.length; i ++) {
            System.out.printf("%5.2f\t | ", averageScoreSubject[i]);
        }
        System.out.println();
        System.out.println("--------------------------------------------------------------------------------");
    }
}

输出结果(非常像一个数据库查询的结果)

输出结果.png

四、多维数组

多维数组就是指数组的元素层层嵌套数组。在定义的时候,第一索引必须指定。执行索引之间不能不能指定索引;多维数组除了最后一层可以储存对象和基本数据类型,其他层次的必须储存对应类型的引用(对应维度的数组引用)

举一个栗子

public class Test {

    public static void main(String[] args) {     
        
        /**多维数组,以一个四维数组为栗子*/
        /**正确的写法*/
        int[][][][]  arrays1 = new int[4][][][];
        int[][][][]  arrays2 = new int[4][3][][];
        int[][][][]  arrays3 = new int[4][3][2][];
        int[][][][]  arrays4 = new int[4][3][2][1];
    
        arrays4[4][3] = new int[7][3]; // 储存对应类型的引用
        
        /**错误的写法
        int[][][][]  arrays5 = new int[][][][];
        int[][][][]  arrays6 = new int[][3][][];
        int[][][][]  arrays7 = new int[4][][2][];
        */
    }
}

你可能感兴趣的:(5. Java中的数组以及多维数组)