类加载过程案例

1. JVM会先去方法区中找有没有相应类的.class存在。如果有,就直接使用;如果没有,则把相关类的.class加载到方法区
2. 在.class加载到方法区时,会分为两部分加载:先加载非静态内容,再加载静态内容
3. 加载非静态内容:
	把.class中的所有非静态内容加载到方法区下的非静态区域内
4. 加载静态内容:
	把.class中的所有静态内容加载到方法区下的静态区域内
	静态内容加载完成之后,对所有的静态变量进行默认初始化
	所有的静态变量默认初始化完成之后,再进行显式初始化
	当静态区域下的所有静态变量显式初始化完后,执行静态代码块
5. 当静态区域下的静态代码块执行完之后就完成整个类的加载
public class Demo01 {
    public static void main(String[] args) {
        B b = new B();
    }
}
class A {
    static String str1 = "父类A的静态变量";
    String str2 = "父类A的非静态变量";
    static {
        System.out.println("执行了父类A的静态代码块");
    }
    {
        System.out.println("执行了父类A的非静态代码块");
    }
    public A() {
        System.out.println("执行了父类A的构造方法");
    }
}

class B extends A {
    static String str1 = "子类B的静态变量";
    String str2 = "子类B的非静态变量";
    static {
        System.out.println("执行了子类B的静态代码块");
    }
    {
        System.out.println("执行了子类B的非静态代码块");
    }
    public B() {
        System.out.println("执行了子类B的构造方法");
    }
}
- 执行了父类A的静态代码块
- 执行了子类B的静态代码块
- 执行了父类A的非静态代码块
- 执行了父类A的构造方法
- 执行了子类B的非静态代码块
- 执行了子类B的构造方法
加载顺序
父类的静态变量
父类的静态代码块
【子类】的静态变量
【子类】的静态代码块
父类的非静态变量
父类的非静态代码块
父类的构造方法
【子类】的非静态变量
【子类】的非静态代码块
【子类】的构造方法
public class LazyLoading {
    public static void main(String[] args) throws Exception {
        //P p;                                  //没有new对象不会被加载
        //Q q = new Q();                        //new对象之后【需要】被加载          ==》staticP	staticQ	noneP	initP	noneQ	initQ
        //System.out.println(P.i);              //打印final值【不需要】加载整个类     ==》8
        //System.out.println(P.j);              //打印非final值【需要】加载整个类     ==》staticP	9
        //System.out.println(P.method1());      //打印static方法【需要】加载整个类    ==》staticP	method1
        //System.out.println(P.method2());      //打印static方法【需要】加载整个类    ==》staticP	method2
        //Class.forName("com.LazyLoading$P");   //【需要】被加载        ==》staticP
    }

    public static class P {
        static final int i = 8;
        static int j = 9;

        private P() {
            System.out.print("initP" + "\t");
        }

        {
            System.out.print("noneP" + "\t");
        }

        static {
            //只要被加载过这个static一定是被打印出来的,因为一个类加载内存之后他有这几个步骤:
            //1.Loading     2.Linking   3.Initialization    这个过程会执行静态语句块。
            System.out.print("staticP" + "\t");
        }

        static String method1() {
            return "method1";
        }

        static final String method2() {
            return "method2";
        }
    }

    public static class Q extends P {
        public Q() {
            System.out.print("initQ" + "\t");
        }

        {
            System.out.print("noneQ" + "\t");
        }

        static {
            System.out.print("staticQ" + "\t");
        }

    }
}
posted @ 2021-12-20 15:54  葉落leaves  阅读(72)  评论(0)    收藏  举报