11

次のクラスがあります:

class Super {
    void foo() {
        System.out.println("Super");
    }
}

class Sub extends Super {
    void foo() {
        super.foo();
        System.out.println("Sub");
    }
}

public class Clazz {
    public static void main(String[] args) {
        new Sub().foo();
    }
}

出力は次のとおりです。

素晴らしい

サブ

質問:

何がsuperありますか?それは親クラスのオブジェクトであり、どの子がフィールドとして保持しますか?

  • もしそうなら、抽象クラスの継承はどのように機能しますか?抽象クラスのインスタンスを作成することはできません。
  • そうでない場合、オーバーライドされたメソッドはどこに保持されますか?

グーグルを試してみましたが、クラスの継承方法などの共通情報しか見つかりませんでした。

アップデート:

あなたはまだ私に明白なことを言っています。たぶん私の質問は少し誤解を招くものでしたが、言い換えてみます:

  • を使用してメソッドを呼び出す場合super、親のメソッドにアクセスしていると言います。しかし、親のオブジェクトなしでこのメソッドを呼び出すにはどうすればよいでしょうか。
  • superと同じですかthisthisご存知のように、は具体的なオブジェクトへの参照です。
4

6 に答える 6

7

子クラスは、その親を表す特別なフィールドを保持しません。あなたは、外側のクラスへの参照を維持している内側のクラスの線に沿って何かを考えているかもしれません。これは特殊なケースであり、スーパーサブクラスが互いにどのように関連しているかを表すものではありません。

内部的には、JVMは「メソッドテーブル」を維持し、ロードされた各クラスをそのクラスで使用可能なメソッドに関連付けます。JVMは、スーパーサブ関係を含む、ロードされたすべてのクラス間の関係についても認識しています。

関数を呼び出すsuperと、JVMは実際にいくつかのことを行います。

  • メソッドが呼び出されているクラスの親を決定します
  • 呼び出される親のメソッドを決定します
  • invokespecial特別な指示( )を使用してメソッドを呼び出します

クラスのクラスファイルを調べると、メソッドに次Subのようなものが表示されます。foo

void foo();
    flags: 
    Code:
        stack=2, locals=1, args_size=1
            0: aload_0       
            1: invokespecial #2        // Method Super.foo:()V
            4: getstatic     #3        // Field java/lang/System.out:Ljava/io/PrintStream;
            7: ldc           #4        // String Sub
            9: invokevirtual #5        // Method java/io/PrintStream.println:(Ljava/lang/String;)V

リストの1行目は、スーパークラスメソッドを呼び出す特別な命令を示しています。

良い読み物は、Java仮想マシン仕様、特にセクション2.11.8です。

于 2013-03-12T17:09:58.030 に答える
3

わかった。コードを1行ずつ見ていきましょう。

'foo'メソッドの最初のステートメントは

super.foo();

fooこれは、スーパークラスメソッドへの明示的な呼び出しです。これは:

 void foo() {
    System.out.println("Super");
}

superこのメソッドをキーワードで明示的に呼び出したため、「Super」がコンソールに出力されます。super現在のクラスを参照するのと同じ方法で、クラスのスーパークラスをthis参照します。

次は、サブクラスの残りのfooメソッドです。

 void foo() {
    super.foo();
    System.out.println("Sub");
}

が呼び出された後super.foo()、「Sub」を出力する次のステートメントに移動します。


プログラムがスーパークラスではなくサブクラスのメソッドに最初に移動する理由は、と呼ばれる原則のためですPolymorphism。つまり、サブクラスはスーパークラスからメソッドを取得し、その動作を変更します。

抽象クラス

抽象クラスのインスタンスを作成することはできませんが、superキーワードを使用すると、それでもスーパークラスの機能にアクセスできます。

Java仮想マシンのコンテキストで

したがって、メソッド呼び出しを行うと、Java仮想マシンは、インスタンスメソッドの場合、ローカルクラスでメソッドを検索します。見つからない場合は、スーパークラスに移動します。の原則を使用するとPolymorphism、JVMはサブクラスで正しいシグニチャを持つメソッドを見つけ、検索を停止します。Polymorphismこれは、Javaのコンテキストで、継承と機能を簡単に説明する方法です。

メソッドをオーバーライドするときは、同じメソッドシグネチャ(メソッドのフィールドの名前、番号、およびタイプ)を持つメソッドをサブクラス定義に追加します。これは、JVMがそれを見つける方法であり、オーバーライドされたメソッドが格納される場所です。

于 2013-03-12T16:49:19.117 に答える
3

superスーパークラスで定義されたメソッド実装を呼び出すことができるキーワードです。それはあなたのサブクラスのフィールドではありません。

そうでない場合、オーバーライドされたメソッドはどこに保持されますか?

これが何を意味するのかよくわかりませんが、次のようになります。

  • 「スーパー」を出力するメソッドは、スーパークラスのクラス定義に含まれています。
  • 「Sub」を出力するメソッドは、サブクラスのクラス定義に含まれています。

SubextendsSuperであるため、クラスSubの定義には、クラスの定義への参照が含まれますSuper

更新された質問への回答:

スーパーでメソッドを呼び出すときは、親のメソッドにアクセスしていると言います。しかし、親のオブジェクトなしでこのメソッドを呼び出すにはどうすればよいでしょうか。

メソッドは単なるコードのブロックであり、実行する必要のある一連のバイトコード命令です。メソッドを呼び出すときのJVMのタスクは、指定したメソッド名とパラメーターから、このコードブロックの場所を判別することです。通常、他の人が言っているように、メソッドが呼び出されたオブジェクトのクラスのクラス定義を最初に調べます。を使用するsuperと、JVMにここを参照せず、代わりに親クラス定義を参照するように指示します。

したがって、a(is )であり、JVMは、キーワードが。のクラス定義でメソッドを構成するコードを検索する必要があることを認識しているため、Superとの個別のインスタンスは必要ありません。SubSub Supernew Sub() instanceof SupertruesuperSuper

これと超同じですか?ご存知のように、これは具体的なオブジェクトへの参照です。

いいえ、同じではありません。thisは現在のオブジェクトへの参照ですが、はオブジェクトsuperへの参照ではありません。代わりに、呼び出されるメソッドを定義するコードをJVMが検索する場所に影響を与えるキーワードです。

于 2013-03-12T16:49:44.857 に答える
1

あなたが書くとき、あなたsuper.foo();はスーパークラスメソッドを呼び出しています。

クラスsubのfooメソッドは、スーパークラスメソッドに命令を追加することにより、Superのfooメソッドをオーバーライドします。

于 2013-03-12T16:49:27.687 に答える
1

サブクラス.super.foo()でのfooメソッドのオーバーライドは、print superを呼び出してから、System.out.println( "Sub");を呼び出します。サブを示しています。

継承のためにこれを試してください

class Super {
    Super()
    {
        System.out.println("1");
    }
    void foo() {
        System.out.println("Super");
    }
}

class Sub extends Super {
    public Sub() {
        // TODO Auto-generated constructor stub
        System.out.println("2");
    }
    void foo() {
       super.foo();
        System.out.println("Sub");
    }
}
于 2013-03-12T16:50:53.950 に答える
0

同時にサブ、スーパー、オブジェクトであるオブジェクトは1つだけです。これらの各クラスのすべての非静的フィールドがあります。クラスは、非静的なものであっても、そのメソッドにコードのコピーを1つだけ必要とします。

于 2013-03-12T16:52:29.737 に答える