你了解数组么?

Java中,声明一个数组的过程中,内存将会如何分配
Java数组初始化一共有多少种方式
基本类型数组和引用类型数组之间,初始化时内存分配机制有什么区别

当我们使用Java数组之前,必须先对数组进行初始化(否则无法使用),当数组的所有元素都被分配了合适的内存空间,并指定了初始值时,数组初始化完成。程序以后将无法改变数组内存的大小以及位置。


数组初始化的两种方式

数组是静态的

这里由于Java语言是典型的静态语言,因此Java的数组是静态的,即当数组被初始化之后,长度将不可以改变。而JavaScript则是动态语言,数组长度可以改变

静态初始化:

初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组的长度!

1
String[] num1= new String[] {"1","2"};

动态初始化:

初始化时程序只指定数组长度,由系统为数组元素分配初始值!

初始值分配规则:

  1. 整数类型:byte short int long 数组元素默认值为0
  2. 浮点类型:float double 数组元素默认值为0.0
  3. 字符类型:char ,数组元素默认值为’\u0000’
  4. 布尔类型:boolean,数组元素的默认值为false
  5. 引用类型(类,接口,数组):数组元素默认值为null

注意事项:

  1. 在我们初始化数组的时候,不可以同时声明数组的长度和给定数组元素的内容
  2. 一旦数组元素初始化完成,内存分配即结束,此时程序只可以改变数组元素的值,而不可以改变数组的长度
  3. Java中的数组变量是一种引用类型的变量,数组变量本身并不是数组本身,只是指向堆内存数组对象而已!
1
String[] num2 = new String[2];

此时,内存示意图如下:

不管采用了数组初始化的哪种方式,一旦数组初始化完成,数组的长度将无法改变!

对于Java程序中所有的引用变量,都不需要经过初始化操作,需要初始化的是该引用变量所引用的对象!


数组初始化的类型

基本类型数组的初始化

对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中

1
2
3
4
/*定义一个int[]类型的数组*/
int[] iArr;
/*静态初始化数组*/
iArr = new int[] {2, 5, -12, 20};

注意:

  1. 基本类型的值存储在栈内存中(这句话是完全错误的),例如上面的iArr数组,都存储在堆内存中。事实上是局部变量是保存在栈内存里保存的,不管是基本类型的变量,还是引用类型的变量,都是存储在各自的方法栈区中,但引用类型变量所引用的对象则总是存储在堆内存中!
  2. Java中,堆内存中的对象不允许直接访问,为了访问堆内存中的对象,通常只能通过引用变量进行访问。(体现了Java的健壮性,避免程序crash)

    事实上,引用变量实际上就是一个指针,只要程序通过引用变量访问属性,或者通过引用变量来调用方法,则该引用变量将会由它所引用的对象替代!

引用类型数组的初始化

引用类型数组的数组元素依然是引用类型的,因此数组元素里存储的还是引用,它指向另一块内存,这块内存里面存储了该引用变量所引用的对象!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

public class Person {

/*年龄*/
public int age;
/*身高*/
public double height;

public void info() {
System.out.println("我的年龄是:" + age + ",我的身高是:" + height);
}

}




public class ReferenceArrayTest {

public static void main(String[] args) {

/*定义一个students数组变量*/
Person[] students;

students = new Person[2];
System.out.println("students所引用的数组长度是:" + students.length);

Person zhang = new Person();
zhang.age = 15;
zhang.height = 158;

Person lee = new Person();
lee.age = 16;
lee.height = 161;
students[0] = zhang;
students[1] = lee;

lee.info();
students[1].info();
}

}

对于上面这段代码,内存分配如下:

最后的内存如下:

注意事项:
对于引用类型的数组而言,它的数组元素其实就是一个引用类型的变量,因此可以指向任何有效的内存(有效指的是强类型的约束,比如Person类型的数组,数组中每个元素的类型都相当于Person类型的变量)