热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

29、es6中的class类的深入理解_类加载的表现形式

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

java中的类是动态加载的,我们先看一下我们常用的类加载方式,先有一个感性的认识,才能进一步
深入讨论,类加载无非就是下面三种方式。
class A{}
class B{}
class C{}
public class Loader{
public static void main(String[] args) throws Exception{
Class aa=A.class;
Class bb=Class.forName("B");
Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
}
}
我们先看.class字面量方式,很多人可能不知道这种方式,因为这种用法不是一般java语法。
通过javap我们可以发现,这种方式的大致等价于定义了一个静态成员变量
static Class class$0;(后面的编号是增长的)
你可以试图再定义一个 static Class class$0,应该会收到一个编译错误(重复定义)。
Class aa=A.class;
就相当于
if(class$0==null){
try{
Class.forName("A");
}
cacth(ClassNotFoundException e){
throw new NoClassDefFoundError(e);
}
}
Class aa=class$0;
可以很清楚的看到,这种类的字面量定义其实不是加载类的方式,而是被编译器处理了,实质
上是使用了Class.forName方法,但是使用这种方式有一个很大的好处就是不用处理异常,因为
编译器处理的时候如果找不到类会抛出一个NoClassDefFoundError。也许你觉得需要处理
ClassNotFoundException这种异常,事实上99%的情况下我们可以把这种异常认为是一个错误。
所以大部分情况我们使用这种方式会更简洁。
最常用的方式就是Class.forName方式了,这也是一个通用的上层调用。这个方法有两个重载,
可能很多人都忽略了第二个方法。
public static Class forName(String name) throws ClassNotFoundException
public static Class forName(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException
第二个方法后面多了两个参数,第二个参数表示是否初始化,第三个参数为指定的类加载器。
在上面的例子中:
Class bb=Class.forName("B");等价于
Class bb=Class.forName("B",true,Loader.class.getClassLoader());
这里要详细说一下这个类的初始化这个参数,如果这个参数为false的话,
类中的static成员不会被初始化,static语句块也不会被执行。
也就是类虽然被加载了,但是没有被初始化,不过在第一次使用时仍然会初始化。
所以我们有时候会看到Class.forName("XXX").newInstance()这样的语句,为什么这里要创建一个
不用的实例呢?不过是为了保证类被初始化(兼容以前的系统)。
其实第二个方法是比较难用的,需要指定类加载器,如果不指定而且又没有安装安全管理器的化,
是无法加载类的,只要看一下具体的实现就明白了。
最本质的方式当然是直接使用ClassLoader加载了,所有的类最终都是通过ClassLoader加载的,
Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
这里通过使用系统类加载器来加载某个类,很直接的方式,但是很遗憾的是通过这种方式加载类,
类是没有被初始化的(也就是初始化被延迟到真正使用的时候).不过我们也可以借鉴上面的经验,加载
后实例化一个对象Class cc=ClassLoader.getSystemClassLoader().loadClass("C").newInstance()。
这里使用了系统类加载器,也是最常用的类加载器,从classpath中寻找要加载的类。
java中默认有三种类加载器:引导类加载器,扩展类加载器,系统类加载器。
java中的类加载有着规范的层次结构,如果我们要了解类加载的过程,需要明确知道哪个类被谁
加载,某个类加载器加载了哪些类等等,就需要深入理解ClassLoader的本质。
以上只是类加载的表面的东西,我们还将讨论深层次的东西。



推荐阅读
  • 本文介绍了如何使用Java编程语言实现凯撒密码的加密与解密功能。凯撒密码是一种替换式密码,通过将字母表中的每个字母向前或向后移动固定数量的位置来实现加密。 ... [详细]
  • 本文探讨了如何选择一个合适的序列化版本ID(serialVersionUID),包括使用生成器还是简单的整数,以及在不同情况下应如何处理序列化版本ID。 ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 深入理解Java字节码:方法调用详解
    本文详细介绍了Java字节码中的方法调用机制,通过具体示例解析了字节码如何处理方法调用及其参数传递。文章由Mahmoud Anouti撰写,原文链接:https://dzone.com/articles/introduction-to-java-bytecode ... [详细]
  • 来自FallDream的博客,未经允许,请勿转载,谢谢。一天一套noi简直了.昨天勉强做完了noi2011今天教练又丢出来一套noi ... [详细]
  • Lua字符串1.字符串常见形式字符串或串(String)是由数字、字母、下划线组成的一串字符。Lua语言中字符串可以使用以下三种方式来表示:•单引号间的一串字符。 ... [详细]
  • java datarow_DataSet  DataTable DataRow 深入浅出
    本篇文章适合有一定的基础的人去查看,最好学习过一定net编程基础在来查看此文章。1.概念DataSet是ADO.NET的中心概念。可以把DataSet当成内存中的数据 ... [详细]
  • 探讨多种方法来确定Java对象的实际类型,包括使用instanceof关键字、getClass()方法等。 ... [详细]
  • 个人博客:打开链接依赖倒置原则定义依赖倒置原则(DependenceInversionPrinciple,DIP)定义如下:Highlevelmo ... [详细]
  • 如何使用Maven将依赖插件一并打包进JAR文件
    本文详细介绍了在使用Maven构建项目时,如何将所需的依赖插件一同打包进最终的JAR文件中,以避免手动部署依赖库的麻烦。 ... [详细]
  • 页面预渲染适用于主要包含静态内容的页面。对于依赖大量API调用的动态页面,建议采用SSR(服务器端渲染),如Nuxt等框架。更多优化策略可参见:https://github.com/HaoChuan9421/vue-cli3-optimization ... [详细]
  • 本文详细探讨了 Android Service 组件中 onStartCommand 方法的四种不同返回值及其应用场景。Service 可以在后台执行长时间的操作,无需提供用户界面,支持通过启动和绑定两种方式创建。 ... [详细]
  • Java连接MySQL数据库的方法及测试示例
    本文详细介绍了如何安装MySQL数据库,并通过Java编程语言实现与MySQL数据库的连接,包括环境搭建、数据库创建以及简单的查询操作。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 本报告记录了嵌入式软件设计课程中的第二次实验,主要探讨了使用KEIL V5开发环境和ST固件库进行GPIO控制及按键响应编程的方法。通过实际操作,加深了对嵌入式系统硬件接口编程的理解。 ... [详细]
author-avatar
芳方程_269
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有