public class MyObj {
static {
System.out.println("MyObj class init.");
}
}
public class Test implements Cloneable, Serializable {
public static void main(String[] args) throws Exception {
Class.forName("com.test.MyObj");
// ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
}
}
Class.forNameとClassLoader.loadClassの違い
クラスローディング
Class.forName
とClassLoader.loadClass
の違いを明確にするために、まず、JVM でのクラスのロード手順を理解する必要があります。クラスのロードは次のように行うことができます。次のステップに分かれています
Class.forName
和ClassLoader.loadClass
的区别, 首先我们需要了解 JVM 中类加载的步骤.类的加载可以分为如下几步
加载: 通过类的全限定名获取到类的二进制流, 然后加载到 JVM 中
验证: 确保Class 文件的字节流中包含的信息符合虚拟机的要求, 并且不会危害虚拟机的安全
准备: 为类变量分配内存空间并设置类变初始值
解析
初始化: 根据用户指定的代码初始化字段和其他资源, 执行 static 块.
Class.forName
当我们通过:
来获取一个 Class 时, 那么其实相当于调用了
Class.forName(className, true, currentLoader)
, 这个方法的第二个参数表示是否需要初始化类. 我们设置为true
, 因此 Class.forName 获取到 Class 对象时, 会自动对类进行初始化的.并且 Class.forName 加载类的 ClassLoader 和调用
Class.forName
所在的类的 ClassLoader 相同.ClassLoader.loadClass
与
Class.forName
不同, 默认情况下ClassLoader.loadClass
并不会初始化类, 即类加载的初始化
步骤没有执行, 因此类中的静态代码块不会执行.并且使用
ClassLoader.loadClass
时, 我们可以指定不同的 ClassLoader. 例如:一个例子
那么上面的代码中,
Class.forName("com.test.MyObj")
的调用会触发 MyObj 的静态代码块的执行, 而ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
Class.forName(className, true, currentLoader)
を呼び出すのと同じです。このメソッドの 2 番目のパラメータは、クラスを初期化する必要があるかどうかを示します。 code> true であるため、Class.forName が Class オブジェクトを取得すると、クラスが自動的に初期化されます。そして、Class.forName は、クラスの ClassLoader と、
Class.forName のクラスをロードします。 code> と呼ばれる ClassLoader も同じです🎜 🎜ClassLoader.loadClass🎜 🎜
Class.forName
とは異なり、ClassLoader.loadClass
はデフォルトではクラスを初期化しません。つまり、クラス読み込みのinitialization
ステップは行われません。実行されるため、クラス内の静的コード ブロックは実行されません。また、
ClassLoader.loadClass
を使用する場合は、別の ClassLoader を指定できます。例: 🎜。 リーリー 🎜一例🎜 リーリー リーリー 🎜上記のコードでは、Class.forName("com.test.MyObj")
の呼び出しにより、MyObj の静的コード ブロックの実行がトリガーされ、ClassLoader.getSystemClassLoader().loadClass( "com.test.MyObj");
はそうではありません。🎜 🎜この方法で使用する利点は何ですか? 🎜 🎜私の個人的な推測は、初期化を高速化するために、Spring IoC はクラスローダーを使用することで、クラス内で初期化コードを実行する必要がなくなります。読み込み速度を高速化します。初期化作業は、このクラスを実際に使用するまで残ります。