0%

java 中 Class.forName 和 loadClass 的区别

前言

java 中使用默认的加载器来加载类主要有两种方式,一种是 Class.forName,另一种是 loadClass,这两者都有对应重载方法,默认一个参数时,都接收全限定类名,用于加载类,但是其具体含义不同,一个会执行类初始化,一个不会默认执行类初始化。

Class.forName

Class.forName 有两个重载函数,分别是:Class<?> forName(String className)Class<?> forName(String name, boolean initialize, ClassLoader loader),其中 forName(String className) 相当于调用 forName(className, true, loader)。更进一步讲,使用Class<?> forName(String className) 默认会执行类的初始化动作。

如下所示,执行 Class<?> forName(String className) 后会输出静态方法和静态代码块的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestLoad {
private static String param = testMethod();

private static String testMethod() {
System.out.println("------------static method----------");
return "------------TestMethod---------------";
}

static {
System.out.println("------------static block------------");
}
}

public class TestLoadMain {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.guozhchun.load.TestLoad");
System.out.println("--------class: " + clazz);
}
}

程序输出如下

1
2
3
------------static method----------
------------static block------------
--------class: class com.guozhchun.load.TestLoad

loadClass

loadClass 也有两个重载函数:loadClass(String name)loadClass(String name, boolean resolve),其中,loadClass(String name) 相当于调用 loadClass(String name, boolean false)。更进一步讲,使用 loadClass(String name) 默认不会执行类初始化动作。

如下所示,使用 loadClass(String name) 并不会执行类的静态代码块和静态方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestLoad {
private static String param = testMethod();

private static String testMethod() {
System.out.println("------------static method----------");
return "------------TestMethod---------------";
}

static {
System.out.println("------------static block------------");
}
}

public class TestLoadMain {
public static void main(String[] args) throws Exception {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("com.guozhchun.load.TestLoad");
System.out.println("--------class: " + clazz);
}
}

程序输出如下

1
--------class: class com.guozhchun.load.TestLoad

总结

Class.forNameloadClass 两者都能进行类加载,并且返回 Class<?> 对象,但是Class.forName 默认会执行类初始化动作,loadClass 默认不会执行类初始化动作。在使用上要根据具体特性进行选择,特别是要加载一些第三方类时,可能该类会有静态属性或静态代码块,如果当前虚拟机并不存在该静态代码块中引用的类,那么选择 Class.forName 就可能报错(因为会执行初始化化,会执行静态类代码块,这时候可能要继续加载其他的类,如果该类不存在,那就会报错),此时应该选择 loadClass 会合适点。