详细介绍java类加载的表现形式

开发 后端
本文介绍的是java类加载的表现形式,希望对你有帮助,一起来看。

Java中的类是动态加载的,我们先看一下我们常用的类加载方式,先有一个感性的认识,才能进一步深入讨论,类加载无非就是下面三种方式。

  1. class A{}  
  2. class B{}  
  3. class C{}  
  4. public class Loader{  
  5. public static void main(String[] args) throws Exception{  
  6. Class aa=A.class;   
  7. Class bb=Class.forName("B");  
  8. Class cc=ClassLoader.getSystemClassLoader().loadClass("C");  
  9. }  

我们先看.class字面量方式,很多人可能不知道这种方式,因为这种用法不是一般java语法。通过javap我们可以发现,这种方式的大致等价于定义了一个静态成员变量

  1. static Class class$0;(后面的编号是增长的) 

 

你可以试图再定义一个 static Class class$0,应该会收到一个编译错误(重复定义)。

  1. Class aa=A.class

就相当于

  1. if(class$0==null){  
  2. try{   
  3. Class.forName("A");  
  4. }  
  5. cacth(ClassNotFoundException e){  
  6. throw new NoClassDefFoundError(e);  
  7. }  
  8. }  
  9. Class aa=class$0

可以很清楚的看到,这种类的字面量定义其实不是加载类的方式,而是被编译器处理了,实质上是使用了Class.forName方法,但是使用这种方式有一个很大的好处就是不用处理异常,因为编译器处理的时候如果找不到类会抛出一个NoClassDefFoundError。也许你觉得需要处理ClassNotFoundException这种异常,事实上99%的情况下我们可以把这种异常认为是一个错误。所以大部分情况我们使用这种方式会更简洁。

最常用的方式就是Class.forName方式了,这也是一个通用的上层调用。这个方法有两个重载,可能很多人都忽略了第二个方法。

  1. public static Class forName(String name) throws ClassNotFoundException  
  2. public static Class forName(String name, boolean initialize,ClassLoader loader) 
  3. throws ClassNotFoundException 

第二个方法后面多了两个参数,第二个参数表示是否初始化,第三个参数为指定的类加载器。

在上面的例子中:

  1. Class bb=Class.forName("B"); 

等价于

  1. Class bb=Class.forName("B",true,Loader.class.getClassLoader()); 

这里要详细说一下这个类的初始化这个参数,如果这个参数为false的话,类中的static成员不会被初始化,static语句块也不会被执行。

也就是类虽然被加载了,但是没有被初始化,不过在第一次使用时仍然会初始化。所以我们有时候会看到Class.forName("XXX").newInstance()这样的语句,为什么这里要创建一个不用的实例呢?不过是为了保证类被初始化(兼容以前的系统)。

其实第二个方法是比较难用的,需要指定类加载器,如果不指定而且又没有安装安全管理器的化,是无法加载类的,只要看一下具体的实现就明白了。

最本质的方式当然是直接使用ClassLoader加载了,所有的类最终都是通过ClassLoader加载的,

  1. Class cc=ClassLoader.getSystemClassLoader().loadClass("C"); 

这里通过使用系统类加载器来加载某个类,很直接的方式,但是很遗憾的是通过这种方式加载类,类是没有被初始化的(也就是初始化被延迟到真正使用的时候).不过我们也可以借鉴上面的经验,加载后实例化一个对象Class cc=ClassLoader.getSystemClassLoader().loadClass("C").newInstance()。

这里使用了系统类加载器,也是最常用的类加载器,从classpath中寻找要加载的类。java中默认有三种类加载器:引导类加载器,扩展类加载器,系统类加载器。java中的类加载有着规范的层次结构,如果我们要了解类加载的过程,需要明确知道哪个类被谁加载,某个类加载器加载了哪些类等等,就需要深入理解ClassLoader的本质。

以上只是类加载的表面的东西,我们还将讨论深层次的东西。

责任编辑:于铁 来源: 互联网
相关推荐

2009-08-04 14:06:39

ASP.NET属性表现

2010-06-09 14:43:27

2022-06-10 10:00:04

数字孪生监管运营流程

2021-08-06 10:02:14

图表饼图联系图表

2016-02-24 11:25:43

DevOps运维

2020-08-20 09:49:10

物联网数据技术

2011-07-12 10:24:17

类加载反射

2023-03-20 00:04:07

2021-06-10 18:59:41

Java编程语言

2010-03-16 14:58:15

Java类加载器

2017-07-12 16:07:49

大数据数据可视化

2023-04-14 17:47:47

2011-07-18 10:21:04

iOS Visual Stu iphone

2009-09-15 13:20:34

LINQ DataCo

2010-08-24 09:19:59

2011-11-03 13:18:19

交换机故障方法

2021-04-07 06:11:37

Css前端CSS定位知识

2021-09-09 16:44:30

数字人民币移动支付中国人民银行

2021-08-28 07:48:04

AndroidActivityRecActivitySta

2022-11-30 16:12:42

智慧城市智慧农业物联网
点赞
收藏

51CTO技术栈公众号