【Java学習ノート】javaの「コンパイルは左を見て、実行は右を見て」をどのように理解するか

1953 ワード

JAvaでの継承は、オブジェクト向けのプログラム設計の大きな特徴であり、サブクラスは親クラスのすべてのメソッドとメンバー変数を継承し、メソッドを書き換えたり、メンバー変数を再割り当てたりしない場合、子クラスは親クラスのメソッドまたは変数を直接呼び出すことができます.また、親クラスをインスタンス化する場合は、子クラスのコンストラクタを使用できます.
しかし、この場合、この親オブジェクトのメソッドと変数を呼び出す場合、親と子のどちらを使用するのでしょうか.まず、2つのクラスを作成します.
public class Animal{
        static String name = "animal";	
        int num = 1;
	public static void sleep() {
		System.out.println("animal sleep");
	}
    public void run() {
		System.out.println("animal run");
	}
}
public class Cat extends Animal{
        static String name = "cat";	
        int num = 2;
	public static void sleep() {
		System.out.println("cat sleep");
	}
        public void run() {
		System.out.println("cat run");
	}
}

Animalクラスには、静的メンバー変数name、メンバー変数num、メソッドrun()および静的メソッドsleep()が宣言され、サブクラスCatにも2つのメソッドが書き換えられていることがわかります.次に,Catの構造法を用いて1つのAnimalをインスタンス化し,さらに1つのCatオブジェクトをインスタンス化する.
public static void main(String args[]) {
		
		Cat cat = new Cat();
		
		Animal animal = new Cat();
		
		System.out.println(cat.num);
		System.out.println(animal.num);
		System.out.println(cat.name);
		System.out.println(animal.name);
		cat.run();
		animal.run();
		cat.sleep();
		animal.sleep();
	}

 
実行後に次のように表示されます.
 
 
2
1
cat
animal
cat run
cat run
cat sleep
animal sleep
 
2つのオブジェクトのそれぞれの変数を出力する場合,Animalオブジェクトはそのサブクラスをコンストラクション関数で使用してサブクラスのメンバ変数値を出力しないが,メンバ変数を呼び出すときは異なり,run()メソッドを呼び出すときはCatと同じ結果をAnimal出力し,静的メソッドsleep()を呼び出すときは,2つのオブジェクトは、それぞれの結果を出力します.
 
このようにまとめると、メンバー変数や静的メソッドを呼び出す場合、「コンパイルは左を見て、実行は左を見て」、すなわちプログラムコンパイル時にAnimalタイプのオブジェクトを作成し、new Cat()を使用してこのAnimalオブジェクトに値を付与するが、最終的に得られるのはやはりAnimalクラスのオブジェクトであり、「=」左のAnimal animalを見るだけでよい.
 
しかし、非静的メソッドを呼び出す場合、AnimalクラスのオブジェクトはCat()でインスタンス化されるため、この非静的メソッドは実行時に書き換えられ、サブクラスのメソッド書き換え後の結果が出力されます.これが「コンパイルは左を見て、実行は右を見て」です.