通过前面章节Java虚拟机类的加载时机的学习,我们知道new 一个类的时候如果这个类还没有初始化就会触发这个类的初始化。那么我们new 一个数组的时候会不会触发类的初始化呢?通过运行下面这个示例,我们可以看到MyTest类的静态代码块并没有执行,说明并没有触发MyTest类的初始化阶段。
package com.geekymv.test.jvm;
public class Test03Array {
public static void main(String[] args) {
MyTest[] myTests = new MyTest[1];
}
}
class MyTest {
static {
System.out.println("MyTest static block");
}
}
修改main方法,打印下myTests的class对象及父class对象。
public static void main(String[] args) {
MyTest[] myTests = new MyTest[1];
System.out.println(myTests.getClass());
System.out.println(myTests.getClass().getSuperclass());
}
输出如下:
class [Lcom.geekymv.test.jvm.MyTest;
class java.lang.Object
说明MyTest[] myTests = new MyTest[1];
这段代码里面触发了另外一个名为[Lcom.geekymv.test.jvm.MyTest
的类的初始化。这并不是一个合法的类的名称,它是一个由Java虚拟机自动生成的,直接继承自java.lang.Object 类。
通过反编译工具javap反编译Test03Array类
javap -c com.geekymv.test.jvm.Test03Array
Compiled from "Test03Array.java"
public class com.geekymv.test.jvm.Test03Array {
public com.geekymv.test.jvm.Test03Array();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: anewarray #2 // class com/geekymv/test/jvm/MyTest
4: astore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_1
9: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class;
12: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_1
19: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class;
22: invokevirtual #6 // Method java/lang/Class.getSuperclass:()Ljava/lang/Class;
25: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
28: return
}
通过反编译后的字节码我们可以看出创建动作由字节码指令anewarray触发,助记符anewarray 表示创建一个引用类型(如类、接口、数组)数组,并将其引用值压入栈顶。
对于数组来说,Javadoc经常将构成数组的元素称为Component,实际上就是将数组降低一个维度后的类型。
「更多精彩内容请关注公众号geekymv,喜欢请分享给更多的朋友哦」