97

Java でのオーバーライドと非表示の違いについて、私は混乱しています。これらがどのように異なるかについて、誰でも詳細を提供できますか? Java チュートリアルを読みましたが、サンプル コードは依然として混乱を招きました。

より明確にするために、私はオーバーライドをよく理解しています。私の問題は、一方がインスタンス レベルにあり、もう一方がクラス レベルにあるという事実を除いて、非表示がどのように違うのかがわからないことです。

Java チュートリアル コードを見ると、次のようになります。

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

次に、サブクラスがありCatます。

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

それから彼らは言う:

このプログラムの出力は次のとおりです。

アニマルのクラスメソッド。

Cat のインスタンス メソッド。

私にとって、クラス メソッドをクラスtestClassMethod()から直接呼び出すとクラスAnimal内でメソッドが実行されるという事実Animalは明らかであり、特別なことは何もありません。testInstanceMethod()次に、 への参照からを呼び出すmyCatので、そのときに実行されたメソッドが のインスタンス内のものであることは明らかですCat

私が見たところ、呼び出しの非表示はオーバーライドと同じように動作しますが、なぜその区別をするのでしょうか? 上記のクラスを使用してこのコードを実行すると:

Cat.testClassMethod();

取得します: Cat のクラス メソッド。 しかし、Cat から を削除すると、次のtestClassMethod()ようになります 。 Animal のクラス メソッド。

これは、親と同じシグネチャを持つ静的メソッドをサブクラスに記述すると、オーバーライドがほとんど行われることを示しています。

うまくいけば、私が混乱している場所を明確にし、誰かが光を当てることができます. よろしくお願いします!

4

17 に答える 17

112

オーバーライドは基本的に遅延バインディングをサポートします。したがって、どのメソッドが呼び出されるかは実行時に決定されます。非静的メソッド用です。

非表示は、他のすべてのメンバー (静的メソッド、インスタンス メンバー、静的メンバー) 用です。早期バインディングに基づいています。より明確に、呼び出されるか使用されるメソッドまたはメンバーは、コンパイル時に決定されます。

あなたの例では、最初の呼び出しAnimal.testClassMethod()はメソッドへの呼び出しであるため、staticどのメソッドが呼び出されるかはほぼ確実です。

2 番目の呼び出し ではmyAnimal.testInstanceMethod()、非静的メソッドを呼び出します。これは、実行時ポリモーフィズムと呼ばれるものです。どのメソッドを呼び出すかは、実行時まで決定されません。

詳細については、Overriding Vs Hidingを参照してください。

于 2012-05-15T04:21:58.947 に答える
19

静的メソッドは隠され、非静的メソッドはオーバーライドされます。「something()」と「this.something()」の呼び出しが修飾されていない場合、違いは顕著です。

言葉では言い表せないので、以下に例を示します。

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

出力:

animal.something
dog.eat
于 2012-05-15T04:28:22.533 に答える
14

これがオーバーライドと非表示の違いです。

  1. 親クラスと子クラスの両方のメソッドがインスタンス メソッドである場合、オーバーライドが呼び出されます。
  2. 親クラスと子クラスの両方のメソッドが静的メソッドである場合、非表示と呼ばれます。
  3. 1 つのメソッドを親で静的にし、子でインスタンスにすることはできません。そしてその逆。

ここに画像の説明を入力

于 2012-05-15T04:25:32.727 に答える
3

私があなたの質問を正しく理解していれば、答えは「あなたはすでにオーバーライドしています」です。

「これは、親と同じ名前の静的メソッドをサブクラスに書くと、ほとんどオーバーライドが行われることを示しています。」

スーパークラスのメソッドとまったく同じ名前のサブクラスのメソッドを記述すると、スーパークラスのメソッドがオーバーライドされます。メソッドをオーバーライドするために @Override アノテーションは必要ありません。ただし、コードが読みやすくなり、実際にメソッドをオーバーライドしていること (たとえば、サブクラス メソッドのスペルを間違えていないこと) をコンパイラがチェックするようになります。

于 2012-05-15T04:17:51.360 に答える
3

オーバーライドは、インスタンス メソッドでのみ発生します。参照変数の型が Animal でオブジェクトが Cat の場合、インスタンス メソッドは Cat から呼び出されます (これはオーバーライドです)。同じ acat オブジェクトに対して、Animal のクラス メソッドが使用されます。

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

出力は次のとおりです。

The instance method in Cat.
Class method in Animal.
于 2012-05-15T04:28:53.890 に答える
0

私の最近の Java 研究に基づく

  • サブクラスに同じ署名を持つ同じメソッドがある場合、メソッドのオーバーライド。
  • サブクラスのメソッド名が同じで、パラメーターが異なる場合のメソッドの非表示この場合、親メソッドをオーバーライドするのではなく、非表示にします。

OCP Java 7 ブックの 70 ~ 71 ページの例:

public class Point {
  private int xPos, yPos;
  public Point(int x, int y) {
        xPos = x;
        yPos = y;
  }

  public boolean equals(Point other){
  .... sexy code here ...... 
  }

  public static void main(String []args) {
   Point p1 = new Point(10, 20);
   Point p2 = new Point(50, 100);
   Point p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //point's class equals method get invoked
  }
}

しかし、次のメインを書くと:

  public static void main(String []args) {
   Object p1 = new Point(10, 20);
   Object p2 = new Point(50, 100);
   Object p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //Object's class equals method get invoked
  }

2番目のmainでは、Objectクラスを静的型として使用しているため、Pointオブジェクトでequalメソッドを呼び出すと、Pointクラスがパラメーターとして到着するのを待っていますが、Objectが来ます。equals(Object o) があるため、 Object クラスの equals メソッドが実行されます。この場合、Point のクラス equals はオーバーライドしませんが、Object クラスの equals メソッドを非表示にします

于 2015-09-10T09:16:59.343 に答える
-1

javaで静的メソッドの隠蔽はどのように行われていますか? Cat クラスは Animal クラスを拡張しています。したがって、Catクラスには両方の静的メソッドがあります(つまり、子クラスの静的メソッドと親クラスの静的メソッドを意味します)しかし、JVMは親静的メソッドをどのように隠しますか? ヒープとスタックをどのように扱っていますか?

于 2015-07-09T04:00:22.017 に答える