Class.forName() 和 ClassLoader.loadClass()和 Class.forName().NewInstance()的区别

http://blog.youkuaiyun.com/shanliangliuxing/article/details/6730800


Class.forName() 和 ClassLoader.loadClass()的区别?

Class.forName() 和 Class.forName().NewInstance()的区别?

Class.forName("xx.xx")等同于Class.forName("xx.xx",true,CALLClass.class.getClassLoader()),第二个参数(bool)表示装载类的时候是否初始化该类,即调用类的静态块的语句及初始化静态成员变量。

ClassLoader loader = Thread.currentThread.getContextClassLoader(); //也可以用(ClassLoader.getSystemClassLoader())

Class cls = loader.loadClass("xx.xx"); //这句话没有执行初始化,其实与Class.forName("xx.xx",false,loader)是一致的,只是loader.loadClass("xx.xx")执行的是更底层的操作。

只有执行cls.NewInstance()才能够初始化类,得到该类的一个实例

 

 

Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4。
Class.forName(className) 实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。注意第二个参数,是指Class被loading后是不是必须被初始化。
ClassLoader.loadClass(className)实际上调用的是ClassLoader.loadClass(name, false),第二个参数指出Class是否被link。

区别就出来了。Class.forName(className)装载的class已经被初始化,而ClassLoader.loadClass(className)装载的class还没有被link。
一般情况下,这两个方法效果一样,都能装载Class。但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。
例 如,在JDBC编程中,常看到这样的用法,Class.forName("com.MySQL.jdbc.Driver"),如果换成了 getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行。
为什么呢?打开com.mysql.jdbc.Driver的源代码看看,
//
// Register ourselves with the DriverManager
//
static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}
原来,Driver在static块中会注册自己到java.sql.DriverManager。而static块就是在Class的初始化中被执行。所以这个地方就只能用Class.forName(className)。

 

 

 

 

Thread.currentThread().getContextClassLoader().loadClass()和Class.forName()返回的Class对象会有啥区别没?还有以前比较老的初始化JDBC的代码里,那句
Class.forName(驱动类全名)
作用是什么啊

作用是把驱动程序的类加载到JVM中. 方便驱动管理程序来实例化驱动对象.(请注意,仅加载类模块)

java里面任何class都要装载在虚拟机上才能运行。Class.forName就是装载类用的(和new不一样,要分清楚)。 

至于什么时候用,你可以考虑一下这个问题,给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?使用方法Class.forName(),不过要再加一点。 
A a = (A)Class.forName("pacage.A").newInstance(); 
这和你 
A a = new A(); 
是一样的效果。 

Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段,动态加载和创建Class对象。

 

Class.forName(驱动类全名) 
  1、他是为了加载JDBC驱动架包的 ,为JDBC中实现其接口的, 他还可以加载别的驱动 .
  2、("sun.jdbc.odbc.JdbcOdbcDriver"),用import的话,程序是不会去加载这个class的。只有通过Class.forName

编译器加载类要依靠classloader, 而classloader有3个级别,从高到低分别是BootClassLoader(名字可能不准确) , ExtClassLoader, AppClassLoader. 
这3个加载器分别对应着编译器去寻找类文件的优先级别和不同的路径:BootClassLoader对应jre/classes路径,是编译器最优先寻找class的地方 
ExtClassLoader对应jre/lib/ext路径,是编译器次优先寻找class的地方 
AppClassLoader对应当前路径,所以也是编译器默认找class的地方 
现在给你分析你的问题我想因为Thread.currentThread().getContextClassLoader().loadClass(className) 
是线程中的类加载器,直接调用起来效率最高,假设在这三个类加载器都找不到你的类,直接用Class.forname()映射 


### Java `Class.forName` 方法详解 #### 什么是 `Class.forName` `Class.forName()` 是 Java 提供的一个静态方法,位于 `java.lang.Class` 类中。此方法接受一个字符串参数作为类的全限定名(即包路径加上类名),并返回对应的 `Class` 对象实例[^1]。 ```java // 加载名为 "com.example.MyClass" 的类 Class<?> clazz = Class.forName("com.example.MyClass"); ``` 该调用不仅会加载目标类至 JVM 虚拟机内存空间内,还会初始化此类——这意味着任何声明于其中的静态成员变量都将被赋予初始值,并且所有的静态代码块会被执行一次[^4]。 #### 基本语法与示例 最简单的形式如下所示: ```java String className = "com.example.MyClass"; try { Class<?> myClass = Class.forName(className); } catch (ClassNotFoundException e) { System.err.println(e.getMessage()); } ``` 如果希望创建新实例,则可以进一步结合反射 API 使用: ```java Object instance; try { Class<?> myClass = Class.forName("com.example.MyClass"); Constructor<?> constructor = myClass.getConstructor(); instance = constructor.newInstance(); } catch (Exception e) { System.err.println(e.getMessage()); } ``` 需要注意的是,在较新的 JDK 版本里推荐使用带有额外参数的形式来显式指定是否要触发初始化以及自定义类加载器[^2]。 #### 反射特性支持 借助 `Class.forName()`, 开发者能够实现更加灵活的应用程序设计模式,比如插件化架构或是数据库连接池管理工具等。这是因为一旦获得了代表某个类型的 `Class` 实例之后,便可以通过它访问到几乎一切关于这个类型的信息,包括但不限于字段、构造函数公共/私有方法等。 例如,当应用程序启动时自动注册 JDBC 驱动程序就是利用了这一功能;只需简单地调用 `Class.forName(driverClassName)` 即可完成驱动加载工作,因为大多数 SQL 数据库提供商都会在其内部定义相应的静态初始化逻辑[^3]。 #### 常见问题解答 - **为什么有时候需要手动调用 `Class.forName()`?** 这通常是为了延迟加载某些资源直到真正需要用到的时候才去处理它们,从而提高性能或减少不必要的依赖关系引入。另外一种情况是在编写通用框架时为了保持良好的扩展性兼容性而采用的方式之一。 - **如何区分 `Class.forName()` `ClassLoader.loadClass()` ?** 尽管两者都可以用来动态加载类文件,但是前者默认情况下会对所加载的目标类进行初始化操作(除非指定了第三个布尔型参数为 false),而后者的标准行为则是仅限于查找并读取字节码而不做其他动作。 - **遇到 `ClassNotFoundException` 怎么办?** 此异常表明虚拟机未能找到请求加载的那个特定类。可能的原因有很多,像是拼写错误、缺少必要的 JAR 文件或者是版本冲突等问题都可能导致这个问题的发生。建议仔细检查项目的构建配置运行环境设置以排除这些潜在隐患。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值