前言

数组是应用最广泛的数据存储结构,是一种简单的复合数据类型,在java语言中,数组被当作一个特殊的对象对待.

特殊点

public static void main(String[] args){  
    int[] arr = new int[10];
    String[][] t_arr = new String[3][4];
    Class aClass = arr.getClass();
    Class tClass = t_arr.getClass();
    //获取本类所有的构造器
    System.out.println(aClass.getDeclaredConstructors().length);  //输出结果  为0
    //获取本类所有声明的字段
    System.out.println(aClass.getDeclaredFields().length);  //输出结果  为0
    //获取本类所有的方法
    System.out.println(aClass.getDeclaredMethods().length);  //输出结果  为0
    //获取本类所有的内部类
    System.out.println(aClass.getDeclaredClasses().length);  //输出结果  为0
    //获取本类所有的注解
    System.out.println(aClass.getDeclaredAnnotations().length);  //输出结果  为0
    //获取超类
    System.out.println(aClass.getSuperclass());  //输出结果  为class java.lang.Object

    //生成的数组对象无构造器,无成员变量,无成员方法,无内部类,也无注解
    //属于object的直接子类
    
    //获取类名
    System.out.println(aClass.getName());    //输出结果  为[I
    System.out.println(tClass.getName());    //输出结果  为[[Ljava.lang.String
    //'['的数目代表了数组的维度."["后面的表示数组的元素类型
 }
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

数组的声明

引用The JavaTM Virtual Machine Specification Second Edition

5.3. Creation and Loading
Array classes do not have an external binary representation; they are created by the Java Virtual Machine rather than by a class loader.
数组类没有外部二进制表示,它是由jvm而非类加载器创建

5.3.3. Creating Array Classes
The following steps are used to create the array class C denoted by N using class loader L. Class loader L may be either the bootstrap class loader or a user-defined class loader.
If L has already been recorded as an initiating loader of an array class with the same component type as N, that class is C, and no array class creation is necessary.
Otherwise, the following steps are performed to create C:
1.If the component type is a reference type, the algorithm of this section (§5.3) is applied recursively using class loader L in order to load and thereby create the component type of C.
2.The Java Virtual Machine creates a new array class with the indicated component type and number of dimensions.
If the component type is a reference type, C is marked as having been defined by the defining class loader of the component type. Otherwise, C is marked as having been defined by the bootstrap class loader.
In any case, the Java Virtual Machine then records that L is an initiating loader for C (§5.3.4).
If the component type is a reference type, the accessibility of the array class is determined by the accessibility of its component type (§5.4.4). Otherwise, the array class is accessible to all classes and interfaces.
文章简要概述: 类加载器检查数组类是否已经被创建,如果有无需创建
否则,jvm根据数组的维度和元素类型创建一个新的数组类
如果数组类的元素是引用类型,则由数组元素的定义类加载器定义,否则由bootstrap定义

数组对象的创建过程

通过jclasslib可以看到数组对象字节码文件在jvm的编译过程

public static void main(String[] args){
    String[] arr = new String[10];
    arr[5] = "java";
    int length = arr.length;
    String[] clone = arr.clone();
}
jvm指令如下:
 0 bipush 10                                      //将数组长度入栈   
 2 anewarray #2 <java/lang/String>                //创建数组"arr",并将数组引用入栈
 5 astore_1                                       //将创建的数组的引用出栈,赋给第2个本地变量,即"arr"
 6 aload_1                                        //将"arr"入栈
 7 iconst_5                                       //数组下标是5,入栈
 8 ldc #3 <java>                                  //将字符串"java"常量值从常量池中推送到栈顶
10 aastore                                        //将栈顶字符串"java",数组下标,字符串"arr"出栈,存入指定数组的指定索引位置
11 aload_1                                        //再次将"arr"推送至栈顶
12 arraylength                                    //将"arr"从栈顶弹出,获取数组的长度
13 istore_2                                       //将栈顶数组长度存入第三个本地变量length
14 aload_1                                        //将"arr"推送至栈顶
15 invokevirtual #4 <[Ljava/lang/String;.clone>   //调用实例方法  clone
18 checkcast #5 <[Ljava/lang/String;>             //检验类型转换
21 astore_3                                       //将栈顶"arr"弹出并存入第四个本地变量"clone"
22 return                                         //从当前方法返回void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

实际的数组元素被储存在堆内存中,数组引用变量被存储在栈内存中.
动态数组改变的只是栈内存的引用,堆内存内原数组长度依旧不变,在标记为不可达状态后,原数组对象等待垃圾回收器回收.

上次更新: 2019-6-24 19:17:56