虚拟机加载类的途径 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是静态加载,2、3是动态加载 两个异常(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())。第二个参数,是指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)。