public class ZiClientB {
public static void main(String[] args) {
System.out.println(MParentB.M_STRING);
}
}
class MParentB{
public static final String M_STRING = UUID.randomUUID().toString();
static {
System.out.println("mparent static block...");
}
}
mparent static block...
a2934bf0-dbac-4a26-b334-97ec67c1f126
关键是常量值是否能够在编译器确定下来,当一个常量值并非编译期间确定的,就不会被放置在调用类的常量池中,运行时会主动地使用常量所在类,这样就会初始化这个类。
即使删除 MParentB.class 也不会影响程序运行
public class ZClientC {
public static void main(String[] args) {
MParentC mParentC = new MParentC();
}
}
class MParentC{
static {
System.out.println("mparent static block ...");
}
}
static {}
在类初始化时候会执行,且只会被执行一次,如果使用 {}
会被执行多次,每一次实例化对象都会执行{}
括号中的代码。
mparent static block ...
public static void main(String[] args) {
MParentC mParentC = new MParentC();
MParentC mParentCa = new MParentC();
}
public static void main(String[] args) {
// MParentC mParentC = new MParentC();
// MParentC mParentCa = new MParentC();
MParentC[] mParentCSs = new MParentC[1];
}
public static void main(String[] args) {
// MParentC mParentC = new MParentC();
// MParentC mParentCa = new MParentC();
MParentC[] mParentCSs = new MParentC[1];
System.out.println(mParentCSs.getClass());
}
当我们创建一个数组时候,数组类型是由 JVM 在运行时创建,无需加载数组的具体类型,所以不会初始化 MParentC 这个类从而也不会执行 static 的代码,通过 getClass 获取起类型为 [
class [Lcom.zidea.jvm.demo.MParentC;
MParentC[][] mParentCSss = new MParentC[1][1];
System.out.println(mParentCSss.getClass());
System.out.println(mParentCSss.getClass().getSuperclass());
class [Lcom.zidea.jvm.demo.MParentC;
class [[Lcom.zidea.jvm.demo.MParentC;
class java.lang.Object
对于数组实例来说,其类型是由 JVM 在运行时动态生成的,表示为[Lcom.zidea.jvm.demo.MParentC 这种形式。动态生成类型其父类型就是Object,对于数组来说的构成数组的元素为Component 实际上就是将数组降低一个维度的类型。
int[] employeeIds = new int[1];
System.out.println(employeeIds.getClass());
System.out.println(employeeIds.getClass().getSuperclass());
class [I
class java.lang.Object
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_1
1: anewarray #2 // class com/zidea/jvm/demo/MParentC
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: iconst_1
16: iconst_1
17: multianewarray #6, 2 // class "[[Lcom/zidea/jvm/demo/MParentC;"
21: astore_2
助记符
anewarray: 其中 anewarray 表示创建一个引用类型的(如类、接口或数组)数组,并将其引用值压入栈顶。
45: iconst_1
46: newarray int
48: astore_3
49: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
助记符
newarray: 其中 newarray 表示创建原始类型(如int、float 或 char)数组,并将其引用值压入栈顶。
之所以没有实例化 mParentC 这是因为只是创建数组的实例,实例类型是 JVM 在运行时创建的。所以这里并没有实例化 mParentC