怪我咯2017-04-18 10:53:03
Class.forName
と ClassLoader.loadClass
の違いを明確にするために、まず、JVM でのクラスのロード手順を理解する必要があります。
クラスのロードは次のように行うことができます。次のステップに分かれていますClass.forName
和 ClassLoader.loadClass
的区别, 首先我们需要了解 JVM 中类加载的步骤.
类的加载可以分为如下几步
加载: 通过类的全限定名获取到类的二进制流, 然后加载到 JVM 中
验证: 确保Class 文件的字节流中包含的信息符合虚拟机的要求, 并且不会危害虚拟机的安全
准备: 为类变量分配内存空间并设置类变初始值
解析
初始化: 根据用户指定的代码初始化字段和其他资源, 执行 static 块.
当我们通过:
Class.forName("com.test.MyObj")
来获取一个 Class 时, 那么其实相当于调用了 Class.forName(className, true, currentLoader)
, 这个方法的第二个参数表示是否需要初始化类. 我们设置为 true
, 因此 Class.forName 获取到 Class 对象时, 会自动对类进行初始化的.
并且 Class.forName 加载类的 ClassLoader 和调用 Class.forName
所在的类的 ClassLoader 相同.
与 Class.forName
不同, 默认情况下 ClassLoader.loadClass
并不会初始化类, 即类加载的 初始化
步骤没有执行, 因此类中的静态代码块不会执行.
并且使用 ClassLoader.loadClass
时, 我们可以指定不同的 ClassLoader. 例如:
ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
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("com.test.MyObj")
的调用会触发 MyObj 的静态代码块的执行, 而 ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
Class.forName(className, true, currentLoader)
を呼び出すのと同じです。このメソッドの 2 番目のパラメータは、クラスを初期化する必要があるかどうかを示します。 code> true であるため、Class.forName が Class オブジェクトを取得すると、クラスが自動的に初期化されます。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 はクラスローダーを使用することで、クラス内で初期化コードを実行する必要がなくなります。読み込み速度を高速化します。初期化作業は、このクラスを実際に使用するまで残ります。返事0