Javaサブクラスと親クラスの初期化中の変数とメソッドの非表示と上書き
2407 ワード
class Parent{
int x=10;
public Parent(){
add(2);
}
void add(int y){
x+=y;
}
}
class Child extends Parent{
int x=9;
void add(int y){
x+=y;
}
public static void main(String[] args){
Parent p=new Child();
System.out.println(p.x);
}
}
出力結果は何ですか?
答えは10です.
結果がなぜ10なのかを理解するには、まず次の知識を理解する必要があります.
(1)Javaにおける変数とメソッドの継承時の非表示と上書きの意味:
非表示:BがAの変数またはメソッドを非表示にした場合、BはAが非表示にした変数またはメソッドにアクセスできませんが、BをAに変換した後、Aが非表示にした変数またはメソッドにアクセスできます.
上書き:BがAの変数またはメソッドを上書きした場合、BはAが上書きした変数またはメソッドにアクセスできないだけでなく、BをAに変換した後もAが上書きした変数またはメソッドにアクセスできない.
(2)Javaにおける変数とメソッドの継承における非表示と上書きのルール:
一、親のインスタンス変数とクラス変数は、クラスの同名変数によって隠すことができる.
二、変数は非表示にするだけで上書きされません.子クラスのインスタンス変数は親クラスのクラス変数を非表示にすることができ、子クラスのクラス変数は親クラスのインスタンス変数を非表示にすることができます.
三、親の静的メソッド布団クラスの同名静的メソッドは非表示であり、親のインスタンスメソッド布団クラスの同名インスタンスメソッドは上書きされる.
四、子クラスの静的メソッドで親クラスのインスタンスメソッドを非表示にすることはできません.また、子クラスのインスタンスメソッドで親クラスの静的メソッドを上書きすることはできません.そうしないと、コンパイラは異常になります.
五、finalキーワードで修飾する最終的な方法は上書きできない.
六、friendly protected public修飾子は影響せず、private属性はアクセス権限の制限を守り、上書きできません.
上記の問題では、サブクラスChildのインスタンスメソッドadd(int y)は、親クラスParentのインスタンスメソッドadd(int y)を上書きし、子クラスのインスタンス変数xは、親クラスを非表示にするインスタンス変数xである.
Childオブジェクトの初期化プロセスは次のとおりです.
1親クラスのインスタンス変数xにメモリ領域を割り当てます.変数xを定義するときに値(int x=10)が割り当てられるため、この値は同時にxに割り当てられます.
2親の非パラメトリック構造関数を呼び出し、Parentの構造関数で唯一のことはadd(2)を呼び出すことである.
3サブクラスのadd(int y)メソッドが親クラスのメソッドを上書きするため、add(2)が実際に呼び出すのはサブクラスのメソッドであり、サブクラスのaddメソッドでは以下のような操作x+=jが行われる.ここで、サブクラスのインスタンス変数xは親クラスのインスタンス変数xを非表示にしているため、この文はサブクラス自体に対するものであるが、この場合、サブクラスのインスタンス変数xに空間が割り当てられず、デフォルト値は0であり、2を加えると2になる.
4親クラスの初期化が完了すると、次に子クラスを初期化し、子クラスのxにメモリ領域を割り当て、9に値を割り当てます.これまでのadd(2)操作は無効です.
5注意Parent p=new Child()この文は、親クラスの参照で子クラスのオブジェクトを指しますが、変数は隠されているだけで上書きされません.したがって、このときのp.x値は子クラスの9ではなく、親クラスの10であるべきです.
出力文を次の文に置き換えると、結果は9になります.
System.out.println(((Child)p).x); // p Child