Javadoc 言う:
呼び出される隠されたメソッドのバージョンはスーパークラスにあり、呼び出されるオーバーライドされたメソッドのバージョンはサブクラスにあります。
私に鐘を鳴らしません。この意味を示す明確な例は高く評価されます。
_public class Animal {
public static void foo() {
System.out.println("Animal");
}
}
public class Cat extends Animal {
public static void foo() { // hides Animal.foo()
System.out.println("Cat");
}
}
_
ここで、Cat.foo()
はAnimal.foo()
を隠すと言われています。静的メソッドはポリモーフィックではないため、非表示はオーバーライドのようには機能しません。したがって、次のことが起こります。
_Animal.foo(); // prints Animal
Cat.foo(); // prints Cat
Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;
a.foo(); // should not be done. Prints Animal because the declared type of a is Animal
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat
d.foo(); // should not be done. Prints Animal because the declared type of d is Animal
_
クラスではなくインスタンスで静的メソッドを呼び出すことは非常に悪い習慣であり、決して実行すべきではありません。
これをインスタンスメソッドと比較してください。インスタンスメソッドはポリモーフィックであるため、オーバーライドされます。呼び出されるメソッドは、オブジェクトの具体的なランタイムタイプによって異なります。
_public class Animal {
public void foo() {
System.out.println("Animal");
}
}
public class Cat extends Animal {
public void foo() { // overrides Animal.foo()
System.out.println("Cat");
}
}
_
その後、次のことが起こります。
_Animal a = new Animal();
Animal b = new Cat();
Animal c = new Cat();
Animal d = null;
a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException
_
まず、メソッド非表示とはどういう意味ですか?
メソッドの非表示は、サブクラスがスーパークラスのクラスメソッドと同じシグネチャでクラスメソッドを定義したことを意味します。その場合、スーパークラスのメソッドはサブクラスによって隠されます。 実行されるメソッドのバージョンは[〜#〜] not [〜#〜]によって決定されます呼び出しに使用されるオブジェクト。実際、メソッドの呼び出しに使用されるタイプの参照変数によって決定されます。
メソッドのオーバーライドとはどういう意味ですか?
メソッドのオーバーライドは、サブクラスがスーパークラスのインスタンスメソッドと同じシグネチャと戻り型(共変型を含む)でインスタンスメソッドを定義したことを意味します。その場合、スーパークラスのメソッドはサブクラスによってオーバーライド(置換)されます。 実行されるメソッドのバージョンは、呼び出しに使用されるオブジェクトによって決定されます。 メソッドの呼び出しに使用される参照変数のタイプによって決定されません。
静的メソッドをオーバーライドできないのはなぜですか?
静的メソッドは、呼び出されるクラスに基づいて静的に(つまり、コンパイル時に)解決されるため、オブジェクトの実行時型に基づいて多相的に解決されるインスタンスメソッドの場合のように動的に解決されるわけではありません。
静的メソッドにはどのようにアクセスする必要がありますか?
静的メソッドには静的な方法でアクセスする必要があります。つまり、インスタンスを使用するのではなく、クラス自体の名前で。
以下は、メソッドのオーバーライドと非表示の短いデモです。
class Super
{
public static void foo(){System.out.println("I am foo in Super");}
public void bar(){System.out.println("I am bar in Super");}
}
class Child extends Super
{
public static void foo(){System.out.println("I am foo in Child");}//Hiding
public void bar(){System.out.println("I am bar in Child");}//Overriding
public static void main(String[] args)
{
Super sup = new Child();//Child object is reference by the variable of type Super
Child child = new Child();//Child object is referenced by the variable of type Child
sup.foo();//It will call the method of Super.
child.foo();//It will call the method of Child.
sup.bar();//It will call the method of Child.
child.bar();//It will call the method of Child again.
}
}
出力は
I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child
明らかに、foo
はクラスメソッドであるため、foo
のバージョンは、Child
。 Super
変数によって参照されている場合、foo
のSuper
が呼び出されます。 Child
変数によって参照されている場合、foo
のChild
が呼び出されます。
一方、、bar
はインスタンスメソッドであるため、bar
のバージョンは、呼び出されるオブジェクト(つまりChild
)によってのみ決定されます。どの参照変数(Super
またはChild
)が呼び出されるかに関係なく、呼び出されるメソッドは常にChild
になります。
メソッドをoverwriteするということは、派生クラスのオブジェクトでメソッドが呼び出されるたびに、新しい実装が呼び出されることを意味します。
メソッドをhideすることは、このクラスのスコープ内(そのメソッドの本体内、または修飾されている場合)でその名前の非修飾呼び出しを意味しますこのクラスの名前で)は完全に異なる関数を呼び出すようになります、親クラスから同じ名前の静的メソッドにアクセスするための資格が必要です。
サブクラスがスーパークラスのクラスメソッドと同じシグネチャを持つクラスメソッドを定義する場合、サブクラスのメソッドはスーパークラスのメソッドを隠します。
隠されたメソッドは静的コンテキストにあると思います。静的メソッドは、それ自体はオーバーライドされません。これは、コンパイル時にコンパイラーがメソッド呼び出し自体の解決を行うためです。そのため、親クラスに存在するものと同じ署名を使用して基本クラスで静的メソッドを定義すると、サブクラスのメソッドはスーパークラスから継承されたメソッドを非表示にします。
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
たとえば、スーパークラスではインスタンスメソッドをオーバーライドできますが、静的ではありません。
Hiding is ParentクラスにはFooという名前の静的メソッドがあり、サブクラスにはFooという静的メソッドもあります。
別のシナリオでは、親にはCatという名前の静的メソッドがあり、サブクラスにはCatという名前のインスタンスメソッドがあります。 (同じシグネチャを持つ静的およびインスタンスは混在できません)。
public class Animal {
public static String getCat() { return "Cat"; }
public boolean isAnimal() { return true; }
}
public class Dog extends Animal {
// Method hiding
public static String getCat() { }
// Not method hiding
@Override
public boolean isAnimal() { return false; }
}
class P
{
public static void m1()
{
System.out.println("Parent");
}
}
class C extends P
{
public static void m1()
{
System.out.println("Child");
}
}
class Test{
public static void main(String args[])
{
Parent p=new Parent();//Parent
Child c=new Child(); //Child
Parent p=new Child(); //Parent
}
}
If the both parent and child class method are static the compiler is responsible for method resolution based on reference type
class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent
Child c=new Child(); //Child
Parent p=new Child(); //Child
}
}
If both method are not static jvm is responsible for method resolution based on run time object