由经典面试题看java中类的加载机制
来源:互联网 发布:淘宝买fifa 编辑:程序博客网 时间:2024/05/19 16:05
这里先修正一个问题,关于静态变量和静态代码块的加载顺序问题,下面表述的先加载静态代码块在加载静态变量的顺序是有问题的,其实是谁写在前面谁先加载,比如我将代码块放在变量前面,代码块就会优先加载,从而访问不到未初始化的变量,非静态变量和代码块也是如此。
- 概述
- 类加载器
- 类加载的过程
- 子类和父类加载顺序
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类继承了另一个java类,这两个类的内部具体的执行过程是什么呢?
比如下面的面试题:
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 blocks2Class B2:static blocks3Class A1:static blocks1Class A2:static blocks2Class B:common blocksi=4,j=3constructor B: i=5,j=4Class A:common blocksi=3,j=2constructor A: i=4,j=3Class A:static void aDisplay(): i=5,j=3
可能这里面最迷惑人的就是两个成员变量了,一个静态的一个非静态的。
其实他们出现在这是貌似没啥太大意义,父类和子类虽然拥有着同名的成员变量,但是,这些变量都独自存在于各自的类中,并有各自的只。
言归正传,由上面的面试题,我们可以得出下面的规律:
- 由经典面试题看java中类的加载机制
- 从经典面试题看java中类的加载机制
- 【面试题】java类加载机制探索
- 【Java面试题】之类加载:从面试题分析Java类加载机制
- java经典面试题(类加载和初始化顺序)
- 经典的Java面试题
- Java由基础到高级面试题经典问答
- Java由基础到高级面试题经典问答
- Java由基础到高级面试题经典问答
- 经典Java面试题-Java中Char类型的运算
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- 关于Java类加载双亲委派机制的思考(附一道面试题)
- java程序员必看的面试题
- Java程序员必看的面试题
- HDU 2050 折线分割平面
- 课程内容回顾
- phpstudy设置数据库远程连接
- 前端技术总结
- iOS xib ScrollView的contentSize
- 由经典面试题看java中类的加载机制
- MairaDB 函数(五)
- Java 内存模型
- 事务 索引 视图
- JavaScript笔记
- 关于硬链接和软连接(符号链接)的区别
- JBDC——Class.forName的作用?为什么要用?
- struts2如何使用拦截器进行用户权限控制
- MySQl——表的操作