室友打了一盘英雄联盟,我学会了类加载

有下面的一个类,请问最后main方法输出是什么?请试着分析打印输出的过程,写出自己的理解。

public class Book {
    static Book book = new Book();
    static int amount = 112;
    static {
        System.out.println("书的静态代码块");
        System.out.println("amount=" + amount);
    }
    int price = 110;

    {
        System.out.println("书的普通代码块");
    }

    Book() {
        System.out.println("书的构造方法");
        System.out.println("price=" + price + ",amount=" + amount);
    }

    public static void staticFunction() {
        System.out.println("书的静态方法");
    }

    public static void main(String[] args) {
        staticFunction();
    }

}

运行代码后输出:
在这里插入图片描述

分析:

  1. 运行main方法,会先发生 Book 类的加载,类加载的过程是:加载->验证->准备->解析->初始化->使用->卸载,在执行初始化这个阶段的时候,会对类所有的静态变量进行初始化,也就是book = null,amount=0。注意:假如使用final修饰静态变量,它是不会初始化的,直接赋值,因为final修饰的变量不可改变;
  2. 第二步是对静态变量赋值,先赋值book = new Book();这个地方new 了一个Book,new Book()需要类加载,然后再进行对象实例化,但是类加载已经进行过了,那么这次就直接实例化对象了。
  3. 实例化Book对象,需要先对Book的成员变量赋值int price = 110,然后执行代码块 { System.out.println(“书的普通代码块”); },所以我们看到控制台先打印了这句话,接着执行构造方法,打印输出 书的构造方法,打印输出price=110,amount=0,price=110很好理解,就是刚才在实例化对象的时候成员变量赋值,那么amount=0呢?这就得联系到刚才初始化类的时候我们给类的静态变量初始化,amount被初始化为0,所以打印了amount=0。
  4. 再往下继续给类的静态变量赋值,amount = 112;,赋值完所有的静态变量后开始执行类的静态块:
static {
   System.out.println("书的静态代码块");
   System.out.println("amount=" + amount);
}
  1. 类加载结束之后,开始执行main方法里面的代码,打印 书的静态方法 这句话。

芜湖~ 看起来没那么复杂啊。但是通过这个小例子,却能很好地理解类加载的机制,尤其是各个代码块执行的顺序,一目了然。

再比如下面的一个类,请问最后main方法输出是什么?

public class Main {
    public static int k = 0;
    static Main t1 = new Main("t1");
    public static Main t2 = new Main("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");

    static {
        print("静态块");
    }

    public Main(String str) {
        System.out.println((++k) + ": " + str + " i=" + i + " n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ": " + str + " i=" + i + " n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String[] args) {
        new Main("init");
    }
}

运行结果:
在这里插入图片描述
分析一番:

  1. 运行main方法会触发类加载,第一步先初始化类的静态变量,k=0,t1=null,t2=null,i=0,n=0。
  2. 然后是静态变量的赋值,k=0,t1=new Main(“t1”),到了new Mian(“t1”)这一步会再次触发类加载,但是类已经加载过了,那么就直接执行对象的初始化了。
  3. 初始化对象,先给对象的成员变量 j 赋值,直接调用了类的静态方法print(“j”),所以打印:1: j i=0 n=0, 执行完后:k=1, i =1, n=1。
  4. 然后执行构造方法 Main(“t1”),输出:2: t1 i=1 n=1,执行完后:k=2, i=2,n=2。
  5. 再往下,执行到t2=new Main(),再次触发类加载,类加载已经进行了,所以还是对象的初始化。注意:类加载只有一次,对象可以初始化多次,那么t2的执行流程和刚才的t1是完全一致的,先执行print(“j”)方法:3: j i=2 n=2,再执行构造函数输出:4: t2 i=3 n=3,执行完后:k=4, i=4,n=4。
  6. 赋值完t1和t2,接下来赋值静态变量 i,执行静态方法:print(“i”),打印输出:5: i i=4 n=4,执行完后k=5, i=5,n=5。
  7. 再赋值静态变量n=99,执行完后k=5, i=5,n=99。
  8. 赋值完所有的静态变量,就开始执行静态代码块了,在静态代码块里,还是执行了静态方法print(“静态块”),打印 6: 静态块 i=5 n=99,执行完后k=6, i=6,n=100。
  9. 最后执行main函数里面的代码 new Main(“init”),同上面一样,先是对成员变量 j 赋值,输出 7: j i=6 n=100,执行完后:k=7, i=7,n=101,再执行构造方法,输出8: init i=7 n=101, 执行完后:k=8, i=8,n=102。

以上就是本题的全部解析了,怎么样?是不是静下心来分析,也没那么难呢?还是那个道理,只要掌握了方法,分析任何问题都只是时间的问题。就跟我们解数学题一样,但是Java代码远没有数学那么枯燥和复杂,当你真的自己分析出来的时候,喜悦感会油然而生的,当然,这份喜悦也只有自己能体会到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值