Java中Class.forName和classloader都可以用来对类进行加载。
- Class.forName(“className”);
其实这种方法调运的是:Class.forName(className, true, ClassLoader.getCallerClassLoader())方法
参数一:className,需要加载的类的名称。
参数二:true,是否对class进行初始化(需要initialize)
参数三:classLoader,对应的类加载器
/**
* Returns the {@code Class} object associated with the class or interface with the given string name, using the given class loader.
* given the fully qualified name for a class or interface (in the same format returned by {@code getname}) this method attempts to locate, load, and link the class or interface.
* The specified class loader is used to load the class or interface.
* If the parameter {@code loader} is null, the class is loaded through the bootstrap class loader.
* The class is initialized only if the {@code initialize} parameter is {@code true} and if it has not been initialized earlier.
*
* 使用给定的类加载器返回与具有给定字符串名称的类或接口关联的对象。
* 给定类或接口的完全限定名称(采用{@code getname}返回的相同格式),此方法尝试查找,加载和链接该类或接口。
* 指定的类加载器用于加载类或接口。如果参数{@code loader}为null,则通过引导类加载器加载该类
* 仅当{@code initialize}参数为{@code true}且之前尚未初始化时,才初始化该类。
*
* <p If {@code name} denotes a primitive type or void, an attempt will be made to locate a user-defined class in the unnamed package whose name is {@code name}.
* Therefore, this method cannot be used to obtain any of the {@code Class} objects representing primitive types or void.
*
* 如果{@code name}表示原始类型或void,则将尝试在名称为{@code name}的未命名包中查找用户定义的类。
* 因此,此方法不能用于获取表示原始类型或void的任何{@code Class}对象。
*
* <p If {@code name} denotes an array class, the component type of the array class is loaded but not initialized.
* 如果{@code name}表示数组类,则该数组类的组件类型已加载但未初始化。
*
* <p For example, in an instance method the expression:
*
* <blockquote>
* {@code Class.forName("Foo")}
* </blockquote>
*
* is equivalent to:
*
* <blockquote>
* {@code Class.forName("Foo", true, this.getClass().getClassLoader())}
* </blockquote>
*
* Note that this method throws errors related to loading, linking or
* initializing as specified in Sections 12.2, 12.3 and 12.4 of <emThe
* Java Language Specification</em.
*
* 此方法会引发与Java语言规范的12.2、12.3和12.4节中指定的加载,链接或初始化有关的错误
*
* Note that this method does not check whether the requested class
* is accessible to its caller.
*
* 此方法不检查其调用者是否可以访问所请求的类
*
* <p If the {@code loader} is {@code null}, and a security
* manager is present, and the caller's class loader is not null, then this
* method calls the security manager's {@code checkPermission} method
* with a {@code RuntimePermission("getClassLoader")} permission to
* ensure it's ok to access the bootstrap class loader.
*
* 如果{@code loader}为{@code null},并且存在安全管理器,并且调用方的类加载器不为null,则此方法使用{@code RuntimePermission( “ getClassLoader”)}权限,以确保可以访问引导程序类加载器。
*
* @param name fully qualified name of the desired class
* @param initialize if {@code true} the class will be initialized.
* See Section 12.4 of <emThe Java Language Specification</em.
* @param loader class loader from which the class must be loaded
* @return class object representing the desired class
*/
@CallerSensitive
public static Class<? forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException
{
Class<? caller = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflective call to get caller class is only needed if a security manager
// is present. Avoid the overhead of making this call otherwise.
caller = Reflection.getCallerClass();
if (sun.misc.VM.isSystemDomainLoader(loader)) {
ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
- ClassLoader.laodClass(“className”);
其实这种方法调运的是:ClassLoader.loadClass(name, false)方法
参数一:name,需要加载的类的名称
参数二:false,这个类加载以后是否需要去连接(不需要linking)
/**
* Loads the class with the specified binary name.
* The default implementation of this method searches for classes in the following order:
*
* 用指定的二进制名称加载类.
* 此方法的默认实现按以下顺序搜索类.
*
* <ol>
*
* <p> Invoke {@link #findLoadedClass(String)} to check if the class has already been loaded. </p</li
*
* 调用{@link #findLoadedClass(String)},以检查是否已加载该类。
*
* <li<p Invoke the {@link #loadClass(String) <ttloadClass</tt} method on the parent class loader. If the parent is <ttnull</tt the class loader built-in to the virtual machine is used, instead. </p</li
* 在父类加载器上调用{@link #loadClass(String)<tt loadClass </ tt}方法。如果父级为<tt null </ tt,则使用虚拟机内置的类加载器。
*
* <p> Invoke the {@link #findClass(String)} method to find the class. </p</li
* 调用{@link #findClass(String)}方法以找到该类。
*
* <p> If the class was found using the above steps, and the <ttresolve</tt flag is true, this method will then invoke the {@link #resolveClass(Class)} method on the resulting <ttClass</tt object.
*
* 如果使用上述步骤找到了该类,并且<tt resolve </ tt标志为true,则此方法将在生成的<tt Class </ tt上调用{@link #resolveClass(Class)}方法对象。
*
* <p Subclasses of <ttClassLoader</tt are encouraged to override {@link #findClass(String)}, rather than this method. </p
*
* <p Unless overridden, this method synchronizes on the result of
* {@link #getClassLoadingLock <ttgetClassLoadingLock</tt} method
* during the entire class loading process.
*
* @param name The <a href="#name"binary name</a of the class
*
* @param resolve If <tttrue</tt then resolve the class
*
* @return The resulting <ttClass</tt object
*
* @throws ClassNotFoundException
* If the class could not be found
*/
protected Class<? loadClass(String name, boolean resolve) throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<? c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
可见Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。
而classloader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。