一、数组初始化

Java 中的数组变量是引用类型的变量。

Java 是静态语言,因此 Java 数组是静态的,即当数组初始化之后,该数组所占的内存空间、数组长度都是不变的。

1、Java 中数组初始化的两种方式:
- 静态初始化:初始化时由程序显示指定每个数组元素的初始值;
- 动态初始化:初始化时只指定数组长度,由系统分配初始值。

public static void main(String[] args) {
    // 静态初始化第一个数组
    String[] books = new String[] {
            "hhh",
            "2333"
    };

    // 静态初始化第二个数组
    String[] names = {
            "aaa",
            "bbb",
            "ccc"
    };

    // 动态初始化第三个数组
    String[] aStr = new String[5];

    System.out.println("books 长度: " + books.length);
    System.out.println("names 长度: " + names.length);
    System.out.println("aStr 长度: " + aStr.length);
}

输出:

java静态数组定义 java static数组_数组

静态初始化方式由系统决定该数组长度;
而动态初始化方式只需指定数组的长度,由系统按如下规则分配初始值:

  • 整数类型(byte, short, int, long):初始值为 0;
  • 浮点类型(float, double):初始值为 0.0;
  • 字符类型(char):初始值为 ‘\u0000’,即 空格的 Unicode 编码;
  • 布尔类型(boolean):初始值为 false;
  • 引用类型(类,接口和数组):初始值为 null 。

2、Java 数组长度不可变(即 Java 数组是静态的):

Java 中一旦数组初始化完成,数组的内存空间分配即结束,程序只能改变数组元素的值,而无法改变数组的长度。但由于 Java 数组是引用类型的变量,因此可以改变一个数组变量所引用的数组,可以造成数组长度可变的假象。

public static void main(String[] args) {
   String[] books = new String[] {
            "hhh",
            "2333"
    };

    String[] names = {
            "aaa",
            "bbb",
            "ccc"
    };

    books = names;

    // 修改 books 数组变量所引用的数组的第二个元素
    books[1] = "wlm";

    System.out.println("names 数组第二个元素: " + names[1]);

}

输出为:

java静态数组定义 java static数组_数组_02

操作说明:

java静态数组定义 java static数组_Java_03

3、使用 Java 数组之前必须进行初始化

代码说明如下:

public static void main(String[] args) {
   // 定义并初始化 nums 数组
    int[] nums = new int[] {1, 2, 3, 4};

    // 定义 prices 数组变量
    int[] prices;

    // prices 数组变量指向 nums 所引用的数组
    prices = nums;

    System.out.println("输出 prices 数组: ");
    for (int i = 0; i < prices.length; i ++) {
        System.out.print(prices[i] + " ");
    }
    System.out.println();

    // 修改 nums 数组第三个元素
    prices[2] = 111;
    System.out.println("nums 第三个元素: " + nums[2]);
}

输出为:

java静态数组定义 java static数组_Java_04

这里的 Java 数组的初始化指的是对 Java 对象进行初始化,而不是对数组变量执行初始化。即在 堆内存 中创建数组对象,也就是为该数组对象分配一块连续的内存空间,这块连续空间的长度就是数组的长度。

即 Java 程序中的引用变量并不需要进行初始化操作,需要进行初始化的是引用变量所引用的对象。

注:Java 局部变量必须制定初始值,如引用之前未指定,则会报编译错误。

java静态数组定义 java static数组_数组_05

4、基本类型数组初始化

程序先为数组分配内存空间,再将数组元素的值存入对应内存里。数组变量存于栈内存中,数组对象存于堆内存中。且一旦数组对象创建成功,数组长度不可改变。

public static void main(String[] args) {
    // 定义 int[] 类型数组变量
    int[] arr;

    // 静态初始化数组, 数组长度为 4
    arr = new int[]{1, 2, 3, 4};
}

执行代码 int[] arr 时,仅定义一个数组变量,内存分配如下:

java静态数组定义 java static数组_Java_06

仅在main栈区定义了一个 arr 变量。

执行 arr = new int[]{1, 2, 3, 4} 静态初始化之后,系统根据数组元素来决定数组的长度。此处数组长度为4,一旦数组对象创建成功,该数组长度不可变,程序只能改变数组元素的值。此时内存分配如下:

java静态数组定义 java static数组_java_07

说明:

  • 所有局部变量都是放在栈内存中的,不管是基本类型的变量,还是引用类型的变量;
  • 但引用类型的变量所引用的对象则总是存储在堆内存中。
    5、引用类型数组初始化

引用类型的数组元素是引用类型的,因此数组元素里存储的是引用,指向另一块内存,该内存存储了该引用变量所引用的对象(包括数组和java对象)。

代码说明如下:
Person 类:

package com.tide.test;

/**
 * Created by wengliemiao on 16/4/4.
 */
public class Person {
    private int age; // 年龄
    private double weight; // 身高

    // 定义一个 info 方法
    public void info() {
        System.out.println("我的年龄是: " + age + ", 我的身高是: " + weight);
    }
}

Run 类:

package com.tide.test;

/**
 * Created by wengliemiao on 16/4/4.
 */
public class Run {
    public static void main(String[] args) {
        // 定义一个 students 数组变量, 类型是 Person[]
        Person[] students ;

        // 动态初始化
        students = new Person[2];

        System.out.println("students 引用数组长度是: " + students.length);

        // 创建一个 Person 实例, 并将这个 Person 实例赋给 wlm 变量
        Person wlm = new Person();
        wlm.setAge(21);
        wlm.setWeight(70);

        // 创建一个 Person 实例, 并将这个 Person 实例赋给 sunlei 变量
        Person sunlei = new Person();
        sunlei.setAge(21);
        sunlei.setWeight(60);

        // 将 wlm 变量赋给第一个数组元素
        students[0] = wlm;
        // 将 sunlei 变量赋给第二个数组元素
        students[1] = sunlei;

        // 输出
        wlm.info();
        students[0].info();
    }
}

输出为:

java静态数组定义 java static数组_初始化_08

上面的代码代表了引用类型数组初始化的典型过程。

内存分配过程如下:

执行 Person[] students 时定义一个引用类型的数组变量:

java静态数组定义 java static数组_java_09

执行动态初始化,由系统为数组元素分配默认的初始值 null:

java静态数组定义 java static数组_Java_10

定义 wlm 和 sunlei 两个引用变量,并指向堆内存中的 Person 对象:

java静态数组定义 java static数组_初始化_11

students 数组的元素也是引用类型的变量,也可以指向堆内存中的对象:

java静态数组定义 java static数组_java静态数组定义_12

此处students[0] 和 wlm 指向同一个 Person 对象,students[1] 和 sunlei 指向同一个 Person 对象,因此 info 输出结果一致。

二、使用数组

  1. 数组元素就是变量;
  2. Java 中没有多维数组。

多维数组就是数组元素为数组的一维数组;
二维数组是数组元素为一维数组的数组;
三维数组是数组元素为二维数组的数组;
……

Java 允许将多维数组当成一维数组处理。

package com.tide.test;

/**
 * Created by wengliemiao on 16/4/4.
 */
public class Run {
    public static void main(String[] args) {
        Object[] objArr = new Object[3];

        objArr[1] = new Object[2];

        Object[] objArr2 = (Object[]) objArr[1];

        objArr2[1] = new Object[3];

        Object[] objArr3 = (Object[]) objArr2[1];

        objArr3[1] = new int[5];

        int[] iArr = (int[]) objArr3[1];

        for (int i = 0; i < iArr.length; i ++) {
            iArr[i] = i * 3 + 1;
        }

        System.out.println( ((int[]) ((Object[]) ((Object[]) objArr[1]) [1]) [1]) [2]);
    }
}

输出为:

java静态数组定义 java static数组_Java_13

内存分配为:

java静态数组定义 java static数组_java_14