JAVA中类的加载机制

java中类的加载机制

看了很多论坛,自己总结了java中类的加载机制,这里先修正一个问题,关于静态变量和静态代码块的加载顺序问题,下面表述的先加载静态代码块在加载静态变量的顺序是有问题的,其实是谁写在前面谁先加载,比如我将代码块放在变量前面,代码块就会优先加载,从而访问不到未初始化的变量,非静态变量和代码块也是如此.

  • 概述
  • 类加载器
  • 类加载的过程
  • 子类和父类加载顺序

1.概述

类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助。

由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。

2.类加载器

类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。

  • Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
  • Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
  • System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

3.类加载的过程

下图是我总结的一个java类被jvm加载的过程。
这里写图片描述

4.子类和父类加载顺序

下图是我总结的一个java类被jvm加载的过程。

比如下面的面试题:

class B{
    //静态变量
    static int i=1;
    //静态语句块
    static {
        System.out.println("Class B1:static blocks"+i);
    }
    //非静态变量
    int j=1;
    //静态语句块
    static{
        i++;
        System.out.println("Class B2:static blocks"+i);
    }
    //构造函数
    public B(){
        i++;
        j++;
        System.out.println("constructor B: "+"i="+i+",j="+j);
    }
    //非静态语句块
    {
        i++;
        j++;
        System.out.println("Class B:common blocks"+"i="+i+",j="+j);
    }
    //非静态方法
    public void bDisplay(){
        i++;
        System.out.println("Class B:static void bDisplay(): "+"i="+i+",j="+j);
        return ;
    }
    //静态方法
    public static void bTest(){
        i++;
        System.out.println("Class B:static void bTest():    "+"i="+i);
        return ;
    }
}

class A extends B{
    //静态变量
    static int i=1;
    //静态语句块
    static {
        System.out.println("Class A1:static blocks"+i);
    }
    //非静态变量
    int j=1;
    //静态语句块
    static{
        i++;
        System.out.println("Class A2:static blocks"+i);
    }
    //构造函数
    public A(){
        super();
        i++;
        j++;
        System.out.println("constructor A: "+"i="+i+",j="+j);
    }
    //非静态语句块
    {
        i++;
        j++;
        System.out.println("Class A:common blocks"+"i="+i+",j="+j);
    }
    //非静态方法
    public void aDisplay(){
        i++;
        System.out.println("Class A:static void aDisplay(): "+"i="+i+",j="+j);
        return ;
    }
    //静态方法
    public static void aTest(){
        i++;
        System.out.println("Class A:static void aTest():    "+"i="+i);
        return ;
    }

public class Tests{

    @Test
    public void test(){
        A a=new A();
        a.aDisplay();
    }

}

执行结果:

Class B1:static blocks2
Class B2:static blocks3
Class A1:static blocks1
Class A2:static blocks2
Class B:common blocksi=4,j=3
constructor B: i=5,j=4
Class A:common blocksi=3,j=2
constructor A: i=4,j=3
Class A:static void aDisplay(): i=5,j=3

可能这里面最迷惑人的就是两个成员变量了,一个静态的一个非静态的。

其实他们出现在这是貌似没啥太大意义,父类和子类虽然拥有着同名的成员变量,但是,这些变量都独自存在于各自的类中,并有各自的只。

言归正传,由上面的面试题,我们可以得出下面的规律:
这里写图片描述

另附上张类加载图,希望对大家有所帮助

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值