JAVA虚拟机加载类的方式解析

虚拟机加载类的途径 
1
、由 new 关键字创建一个类的实例 
  
在由运行时刻用 new 方法载入 
  
如:Dog dog new Dog(); 
2
、调用 Class.forName() 方法 
  
通过反射加载类型,并创建对象实例 
  
如:Class clazz Class.forName“Dog”); 
       Object dog
clazz.newInstance(); 
3
、调用某个 ClassLoader 实例的 loadClass() 方法 
  
通过该 ClassLoader 实例的 loadClass() 方法载入。应用程序可以通过继承 ClassLoader 实现自己的类装载器。 
  
如:Class clazz classLoader.loadClass“Dog”); 
       Object dog
clazz.newInstance();
三者的区别: 
1
2使用的类加载器是相同的,都是当前类加载器。(即:this.getClass.getClassLoader)。3由用户指定类加载器。如果需要在当前类路径以外寻找类,则只能采用第3种方式。第3种方式加载的类与当前类分属不同的命名空间。另外,1是静态加载,23是动态加载 
两个异常(exception) 
静态加载的时候如果在运行环境中找不到要初始化的类,抛出的是NoClassDefFoundError,它在JAVA的异常体系中是一个Error 
动态加载的时候如果在运行环境中找不到要初始化的类,抛出的是ClassNotFoundException,它在JAVA的异常体系中是一个checked异常 
Class.forName
ClassLoader.loadClass区别 
Class
的装载包括3个步骤:加载(loading,连接(link,初始化(initialize
Class.forName(className)
实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。第二个参数,是指Classloading后是不是必须被初始化。 
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
的源代码如下: 
Java
代码

// Register ourselves with the DriverManager   

static {   

    try {   

        java.sql.DriverManager.registerDriver(new Driver());   

    } catch (SQLException E) {   

        throw new RuntimeException("Can't register driver!");   

    }   

}  

原来,Driverstatic块中会注册自己到java.sql.DriverManager。而static块就是在Class的初始化中被执行。 
所以这个地方就只能用Class.forName(className) 
对于相同的类,JVM最多会载入一次。但如果同一个class文件被不同的ClassLoader载入,那么载入后的两个类是完全不同的。因为已被加载的类由该类的类加载器实例与该类的全路径名的组合标识。设有 packagename.A Class ,分别被类加载器 CL1 CL2 加载,所以系统中有两个不同的 java.lang.Class 实例: <CL1, packagename.A> <CL2, packagename.A>
北大青鸟网上报名
北大青鸟招生简章