JVM_类的加载、连接与初始化(二)

上一篇

当一个常量的值并非编译期间内可以确定的,那么其值就不会放到调用类的常量池中。这时候程序运行时,会导致主动使用这个常量所在类,即让该类初始化。

先上代码块

import java.util.UUID;

public class Test3 {
    public static void main(String[] args){
        System.out.println(Parent3.str);
    }
}
class Parent3{
    public static final String str = UUID.randomUUID().toString();
    static {
        System.out.println("parent3 static block");
    }
}

实例化Parent4

public class Test4 {
    public static void main(String[] args){
        Parent4 parent4 = new Parent4();
        System.out.println(parent4.getClass());
    }

}

class Parent4{
    static {
        System.out.println("parent4 static block");
    }
}

运行结果:
parent4 static block
class Parent4

class Parent4 说明该类型是一个Parent4类型,静态方法也被打印出来了,class被主动使用。再看看下面代码。

public class Test4 {
    public static void main(String[] args){
        Parent4[] parents = new Parent4[3];
        System.out.println(parents.getClass());
    }

}

class Parent4{
    static {
        System.out.println("parent4 static block");
    }
}

运行结果:
class [LParent4;

以上代码并没有打印静态方法,因为该类型是一个数组,在JVM在运行期间,类似动态代理创建的,标记:[L,并没有创建Parent4实例,附上编译文件内容。

public class Test4 {
  public Test4();
    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_3
       1: anewarray     #2                  // class Parent4
       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: return
}

再试试创建二维数据,并查看输出。

public class Test4 {
    public static void main(String[] args){
        Parent4[][] parents = new Parent4[2][2];
        System.out.println(parents.getClass());
    }

}

class Parent4{
    static {
        System.out.println("parent4 static block");
    }
}
运行结果:
class [[LParent4;

类型是一个二维数组,标记:[[L

public class Test4 {
  public Test4();
    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_3
       1: anewarray     #2                  // class Parent4
       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: return
}

D:\workspace-for-yun\untitled\out\production\TestJVM>javap -c Test4.class
Compiled from "Test4.java"
public class Test4 {
  public Test4();
    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_2
       1: iconst_2
       2: multianewarray #2,  2             // class "[[LParent4;"
       6: astore_1
       7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: aload_1
      11: invokevirtual #4                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
      14: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      17: return
}

查看三种实例的类型及其父类型。

public class Test4 {
    public static void main(String[] args){
        System.out.println("*****引用类型*****");
        Parent4 parent4 = new Parent4();
        Parent4[] parents = new Parent4[2];
        Parent4[][] parent2s = new Parent4[2][2];
        System.out.println("parent4类型:"+parent4.getClass());
        System.out.println("parent4父类型:"+parent4.getClass().getSuperclass());
        System.out.println("parents类型:"+parents.getClass());
        System.out.println("parents父类型:"+parent4.getClass().getSuperclass());
        System.out.println("parent2s类型:"+parent2s.getClass());
        System.out.println("parent2s父类型:"+parent4.getClass().getSuperclass());
        System.out.println("*****基本类型*****");
        int[] list = new int[1];
        System.out.println("list类型:"+list.getClass());
        System.out.println("list父类型:"+list.getClass().getSuperclass());
    }

}

class Parent4{
    static {
        System.out.println("parent4 static block");
    }
}

运行结果:
*****引用类型*****
parent4 static block
parent4类型:class Parent4
parent4父类型:class java.lang.Object
parents类型:class [LParent4;
parents父类型:class java.lang.Object
parent2s类型:class [[LParent4;
parent2s父类型:class java.lang.Object
*****基本类型*****
list类型:class [I
list父类型:class java.lang.Object

总结:1.对于数组实例来说,其类型是由JVM在运行时期间动态生成的,表示为[[L....,这种形式的。动态生成的类型,其父类就是Object。

对于数组来说,JavaDoc经常将构成数组的元素为Component,实际上就是将数组降低一个维度后的类型。

反编译以上的class文件进行查看。

public class Test4 {
  public Test4();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String *****引用类型*****
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: new           #5                  // class Parent4
      11: dup
      12: invokespecial #6                  // Method Parent4."<init>":()V
      15: astore_1
      16: iconst_2
      17: anewarray     #5                  // class Parent4
      20: astore_2
      21: iconst_2
      22: iconst_2
      23: multianewarray #7,  2             // class "[[LParent4;"
      27: astore_3
      28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: new           #8                  // class java/lang/StringBuilder
      34: dup
      35: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
      38: ldc           #10                 // String parent4类型:
      40: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      43: aload_1
      44: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      47: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      50: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      53: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      56: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      59: new           #8                  // class java/lang/StringBuilder
      62: dup
      63: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
      66: ldc           #15                 // String parent4父类型:
      68: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      71: aload_1
      72: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      75: invokevirtual #16                 // Method java/lang/Class.getSuperclass:()Ljava/lang/Class;
      78: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      81: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      84: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      87: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      90: new           #8                  // class java/lang/StringBuilder
      93: dup
      94: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
      97: ldc           #17                 // String parents类型:
      99: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     102: aload_2
     103: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     106: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     109: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     112: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     115: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     118: new           #8                  // class java/lang/StringBuilder
     121: dup
     122: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
     125: ldc           #18                 // String parents父类型:
     127: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     130: aload_1
     131: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     134: invokevirtual #16                 // Method java/lang/Class.getSuperclass:()Ljava/lang/Class;
     137: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     140: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     143: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     146: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     149: new           #8                  // class java/lang/StringBuilder
     152: dup
     153: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
     156: ldc           #19                 // String parent2s类型:
     158: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     161: aload_3
     162: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     165: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     168: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     171: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     174: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     177: new           #8                  // class java/lang/StringBuilder
     180: dup
     181: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
     184: ldc           #20                 // String parent2s父类型:
     186: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     189: aload_1
     190: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     193: invokevirtual #16                 // Method java/lang/Class.getSuperclass:()Ljava/lang/Class;
     196: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     199: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     202: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     205: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     208: ldc           #21                 // String *****基本类型*****
     210: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     213: iconst_1
     214: newarray       int
     216: astore        4
     218: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     221: new           #8                  // class java/lang/StringBuilder
     224: dup
     225: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
     228: ldc           #22                 // String list类型:
     230: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     233: aload         4
     235: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     238: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     241: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     244: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     247: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     250: new           #8                  // class java/lang/StringBuilder
     253: dup
     254: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
     257: ldc           #23                 // String list父类型:
     259: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     262: aload         4
     264: invokevirtual #12                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
     267: invokevirtual #16                 // Method java/lang/Class.getSuperclass:()Ljava/lang/Class;
     270: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     273: invokevirtual #14                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     276: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     279: return
}

助记符:

anewarray:表示创建一个引用类型的(如:类、接口、数组)数组,并将其引用值压入栈顶。

multianewarray:表示创建一个引用类型的(如:类、接口、数组)二维数组,并将其引用值压入栈顶。

newarray:表示创建一个指定的原始类型(如int、float、char等)的数组,并将其引用值压入栈顶。

注:二维数据int[][]属于一个引用类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值