-1

クラスベース:

public class Base {
    private String name = "base";

    public Base() {
        tellName();
        printName(name);
    }

    public void tellName() {
        System.out.println("Base tell name:" + name);
    }

    public void printName(String name) {
        System.out.println("Base print name:" + name);
    }
}

クラス派生:

public class Derived extends Base {
    private String name = "Derived";

    public Derived() {
        tellName();
        printName(name);
    }

    public void tellName() {
        System.out.println("Derived tell name:" + name);
    }

    public void printName(String name) {
        System.out.println("Derived print name:" + name);
    }

    public static void main(String[] args) {
        Derived derived = new Derived();
    }
}

結果:

Derived tell name:null
Derived print name:base
Derived tell name:Derived
Derived print name:Derived

最近、こんな質問をされました。考えてみましたが、なぜこのプログラム部分がこのような実行結果になるのか、はっきりした答えはありませんでした。誰かが私がそのような問題を分析するのを手伝ってくれることを願っています. どうもありがとう!^-^

派生条件でのコンストラクターの実行プロセスを知りたいだけです。

4

2 に答える 2

0

で実行が開始されDerived.mainます。これにより の新しいインスタンスが作成されるDerivedため、Derivedコンストラクターが呼び出されます。これは、サブオブジェクトBaseを初期化してから を呼び出すコンストラクタを呼び出すことから始まります。動的ディスパッチにより、呼び出される は isであり、 notです。これが出力するテキストは、初期化されたサブオブジェクトのではなく、まだ初期化されていないサブオブジェクトの を参照しているため、出力されます。コントロールはコンストラクターで再開され、次にサブオブジェクトの. 動的ディスパッチにより、呼び出されます。のBasenametellNametellNameDerived.tellNameBase.tellNameDerivednameBasename"Derived tell name:null"BaseprintNameBasenameDerived.printNamename表示されるのはその引数であり、(先ほど見たように)サブオブジェクトnameからのものです。Baseしたがって"Derived print name:base"Baseサブオブジェクトnameは以前に に初期化されているため、出力されます"base"。コンストラクターが完了し、コンストラクターBaseで制御が再開さDerivedれます。これにより、Derivedサブオブジェクトのnameto が初期化され、観測された結果とともにandが"Derived"呼び出されます。Derived.tellNameDerived.printName

追加の観察として、ここで問題が発生するのは、Java がコンストラクターで仮想呼び出しを動的にディスパッチするためであることに注意してください。C++ などの他の言語にはありません。たとえば、以下を参照してください。

http://www.parashift.com/c++-faq-lite/calling-virtuals-from-ctors.html

于 2013-10-14T15:45:34.480 に答える