【java】类的加载和对象的构造(实例化)过程及顺序

1.类的加载

1.1 什么类的加载load?(Node类的加载)

答.从硬盘上找到Node.class,解析该文件内容,生成Node类,把Node类的信息存放在内存的方法区

1.2 什么情况下回触发类的加载?并且该类不在内存中

(1)按需加载(懒加载过程)

          a.实例化该类的一个对象 new Node(1);

          b.使用类的静态属性或者静态方法 Main.merge(…)

          c.用到子类,必须要有父类 new CNode

         d.先加载父类的静态代码块,再加载子类的静态代码块

 

1.3 其他规则

静态属性的初始化顺序:

按代码的书写顺序,执行

a.静态属性定义时的初始化

b.静态代码

2.代码块

代码块定义:使用“{}”定义的一段代码;

构造代码块是跟着对象的加载而加载的。

2.1 普通代码块

普通代码块:定义在方法中的代码块;

public class Test1 {
    public static void main(String[] args) {
        {
            //普通代码块
            int a=10;
            System.out.println(a);
        }
        int a=20;
        System.out.println(a);
    }
}

2.2 构造块

构造块:定义在类中的代码块(不加修饰符)

class A{
    //定义在类中,不加任意修饰符
    {
        System.out.println("A的构造块");
    }
    //构造方法
    public A(){
        System.out.println("A的构造方法");
    }
}
public class Test2 {
    public static void main(String[] args) {
        new A();
        new A();
    }
}

【java】类的加载和对象的构造(实例化)过程及顺序_第1张图片

通过上述代码可以发现:构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块。所以构造块可以进行简单的逻辑操作(在调用构造方法之前)。

2.3 静态代码块

静态代码块:使用static定义的代码块,它是跟着类的加载而加载的。

根据静态代码块所在的类不同又可分为以下两种类型:

1.在非主类中的静态代码块

2.在主类中的静态代码块

2.3.1 在非主类中的静态代码块

class B{
    //构造块
    {
        System.out.println("B类的构造块");
    }
    //代码方法
    public B(){
        System.out.println("B类的构造方法");
    }
    //静态代码块
    static {
        System.out.println("B类的静态代码块");
    }
}
public class Test3 {
    public static void main(String[] args) {
        System.out.println("==============================");
        new B();
        new B();
        System.out.println("==============================");
    }
}

【java】类的加载和对象的构造(实例化)过程及顺序_第2张图片

可以发现:

                1.在非主类的静态代码块中,在类加载时执行,优先于构造块执行

                2.无论产生多少实例化对象,静态代码块只执行一次

静态块的主要作用是为static属性进行初始化!

2.3.2 在主类中的静态代码块

public class Test4 {
    //构造块
    {
        System.out.println("Test4类的构造块");
    }

    //构造方法
    public Test4(){
        System.out.println("Test4类的构造方法");
    }
    //静态代码块
    static {
        System.out.println("Test4类的静态代码块");
    }

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

【java】类的加载和对象的构造(实例化)过程及顺序_第3张图片

在主类中定义的静态块,优先于主方法(main)执行,在JVM启动时执行,当编译执行时JVM会首先加载主类,此时主类中的静态代码块就会执行。

3.对象的构造/实例化 new Node

3.1 规则

1.优先初始化父类的属性,(和下面的执行顺序相同)

2.按照下面的顺序执行初始化

a.按照代码书写顺序,执行定义时和构造代码块

b.再去执行构造方法

3.静态代码块只在加载时执行一次,先执行父类的静态代码块,再执行子类的静态代码块。

3.2关于执行顺序的问题

1.父类的加载在子类之前

2.父类的构造方法在子类之前调用

3.static属性初始化是在类的加载时执行(按顺序执行)

1)定义时初始化

2)构造代码块时初始化

4.普通属性初始化是在对象的构造时执行(按顺序执行)

1)定义时初始化

2)构造代码块时初始化

3)构造方法时初始化

5.只有用到类,才会加载类

class Hello{
    //构造方法
    public Hello(){
        System.out.println("1.Hello父类的构造方法");
    }
    //非静态代码块
    {
        System.out.println("2.Hello父类非静态代码块");
    }
    //静态代码块
    static{
        System.out.println("3.Hello父类静态代码块");
    }
}
public class HelloA extends Hello{
    public HelloA(){
        System.out.println("4.helloA构造方法");
    }
    //非静态代码块
    {
        System.out.println("5.HelloA非静态代码块");
    }
    //静态代码块
    static{
        System.out.println("6.HelloA静态代码块");
    }

    public static void main(String[] args) {
        System.out.println("7.---start---");
        new HelloA();
        new HelloA();
        System.out.println("8.---end---");
    }
}

按照上面讲的执行顺序执行:因为先用到了主类HeoolA,所以先加载了静态代码块;

执行结果:

【java】类的加载和对象的构造(实例化)过程及顺序_第4张图片

class Hello1{
    //构造方法
    public Hello1(){
        System.out.println("1.Hello1父类的构造方法");
    }
    //非静态代码块
    {
        System.out.println("2.Hello1父类非静态代码块");
    }
    //静态代码块
    static{
        System.out.println("3.Hello1父类静态代码块");
    }
}
class Hello2 extends Hello1 {
    public Hello2() {
        System.out.println("4.hello2构造方法");
    }

    //非静态代码块
    {
        System.out.println("5.Hello2非静态代码块");
    }

    //静态代码块
    static {
        System.out.println("6.Hello2静态代码块");
    }

}
public class Test{
    public static void main(String[] args) {
        System.out.println("7.---start---");
        new Hello2();
        new Hello2();
        System.out.println("8.---end---");
    }
}

运行结果:

【java】类的加载和对象的构造(实例化)过程及顺序_第5张图片

 

注:代码块的内容参考本文章!!!

 

 

 

 

你可能感兴趣的:(【java】类的加载和对象的构造(实例化)过程及顺序)