序文
どのような状況下ではそれがクラスのロードをトリガでしょうか?これにはいくつかの状況について話をしたコードのデモを結合します、我々は手助けをしたいです。
クラスのロードタイミング
負荷:クラスローディングプロセスの最初のフェーズを開始するときは?この時点まで、義務を実行していないJava仮想マシンの仕様は自由に把握する特定の仮想マシンに与えることができます。しかし、初期段階のため、仮想マシンの仕様、次のような状況の厳格な要件は、クラスが初期化されていない場合は、その初期化をトリガーする必要があり、すぐにクラスを初期化する必要があります。
クラスのインスタンスを作成します。
クラスローダを確認するために、我々は、JVM引数を設定します
-XX:+TraceClassLoading 监控类的加载
复制代码
次のようにIDEの構成です。
デモコード:
public class ClassLoadInstance {
static {
System.out.println("ClassLoadInstance类初始化时就会被执行!");
}
public ClassLoadInstance() {
System.out.println("ClassLoadInstance构造函数!");
}
}
public class ClassLoadTest {
public static void main(String[] args) {
ClassLoadInstance instance = new ClassLoadInstance();
}
}
复制代码
結果:
結論:
新しいClassLoadInstanceインスタンスが、ClassLoadInstanceがロードされた見つけたとき、そのオブジェクトの新しいインスタンスを作成するには、クラスローダがトリガされます。
アクセスクラスの静的変数
デモコード:
public class ClassLoadStaticVariable {
static {
System.out.println("ClassLoadStaticVariable类初始化时就会被执行!");
}
public static int i = 100;
public ClassLoadStaticVariable() {
System.out.println("ClassLoadStaticVariable构造函数!");
}
}
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println(ClassLoadStaticVariable.i);
}
}
复制代码
結果:
結論:
私はクラスClassLoadStaticVariable静的変数にアクセスする場合、それはClassLoadStaticVariableクラスがロードされていたので、静的変数は、クラスは、クラスのロードをトリガするアクセス。
注意:
静的変数の最終修正をアクセスする場合は、コンパイル時に、これが定数プール内の定数となっているので、クラスのロードをトリガしません。
アクセスクラスの静的メソッド
デモコード:
public class ClassLoadStaticMethod {
static {
System.out.println("ClassLoadStaticMethod类初始化时就会被执行!");
}
public static void method(){
System.out.println("静态方法被调用");
}
public ClassLoadStaticMethod() {
System.out.println("ClassLoadStaticMethod构造函数!");
}
}
public class ClassLoadTest {
public static void main(String[] args) {
ClassLoadStaticMethod.method();
}
}
复制代码
結果:
結論:
クラスにアクセスするための静的メソッドは、メソッドをClassLoadStaticMethod場合は、ClassLoadStaticMethodクラスがロードされ、クラスにアクセスするので、静的メソッドは、クラスのロードをトリガーしますがわかりました。
反射
デモコード:
package classload;
public class ClassLoadStaticReflect {
static {
System.out.println("ClassLoadStaticReflect类初始化时就会被执行!");
}
public static void method(){
System.out.println("静态方法被调用");
}
public ClassLoadStaticReflect() {
System.out.println("ClassLoadStaticReflect构造函数!");
}
}
public class ClassLoadTest {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("classload.ClassLoadStaticReflect");
}
}
复制代码
結果:
結論:
反射型ClassLoadStaticReflectが得られたとき、それはClassLoadStaticReflectクラスがロードされる発見された、反射は、クラスローディングをトリガします。
クラスを初期化すると、クラスがまだ父親の初期化、親クラスの最初のトリガの初期化を見つけていません
デモコード:
//父类
public class ClassLoadSuper {
static {
System.out.println("ClassLoadSuper类初始化时就会被执行!这是父类");
}
public static int superNum = 100;
public ClassLoadSuper() {
System.out.println("父类ClassLoadSuper构造函数!");
}
}
//子类
public class ClassLoadSub extends ClassLoadSuper {
static {
System.out.println("ClassLoadSub类初始化时就会被执行!这是子类");
}
public static int subNum = 100;
public ClassLoadSub() {
System.out.println("子类ClassLoadSub构造函数!");
}
}
public class ClassLoadTest {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoadSub classLoadSub = new ClassLoadSub();
}
}
复制代码
結果:
業績を読んで、その道路のオンライン古典的な顔の質問には見られない( クラスについて話をインスタンス化ため ?)それはまた、非常に明確です。父の静的クラス変数/コードの静的ブロック- >静的変数/コードの静的ブロックの別のサブクラス- >親クラスのコンストラクタ- >サブクラスのコンストラクタ結論:
サブクラスClassLoadSubの例としては、親クラスClassLoadSuperが最初にロードされたので、クラスを初期化するとき、クラスがまだ父親の初期化、親クラスの最初のトリガの初期化を見つけていません
仮想マシンが起動すると、main()メソッドの定義は、クラスを初期化します
デモコード:
package classload;
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println(ClassLoadSub.subNum);
}
}
复制代码
結果:
結論:
仮想マシンがClassLoadSub、ClassLoadSuper、ClassLoadTest及び他のクラスがロードされていても、パワーオンが、最初にされたときには、クラスする最初のトリガクラスローディングのmain()メソッドを定義ClassLoadTestをロードします。
演習とまとめ
私たちのすべてのために行わトリガークラスのロード6つのタイミング解析、それは問題ではないことを言うためにもっと何かを考えていないですか?次に、我々は今、クラスローダに古典的な顔の質問を分析します。
class SingleTon {
private static SingleTon singleTon = new SingleTon();
public static int count1;
public static int count2 = 0;
private SingleTon() {
count1++;
count2++;
}
public static SingleTon getInstance() {
return singleTon;
}
}
public class ClassLoadTest {
public static void main(String[] args) {
SingleTon singleTon = SingleTon.getInstance();
System.out.println("count1=" + singleTon.count1);
System.out.println("count2=" + singleTon.count2);
}
}
复制代码
結果:
分析:
- SingleTon.getInstance()は、シングルトンクラスのロードをトリガする、静的メソッドを呼び出します。
- シングルトンクラスローディングの初期化、静的変数を初期化するためです。
- 実行される最初のプライベート静的シングルトンシングルトン=新しいシングルトン();,コンストラクタ、COUNT1、COUNT2を呼び出した後です1。
- 順番パブリック静的に実行されないint型COUNT1;値が、それはまだCOUNT1 1です。
- 順次のpublic static int型COUNT2 = 0を実行するステップとCOUNT2は、したがって、ゼロになります。
個人公開番号
懸念へようこそ、私たちは一緒に議論し、一緒に勉強します。