答群友問:Java静的内部クラス、一般内部クラスなどの理解
3693 ワード
昨日、あるグループの友达はあるグループの中で一つの問題を出しました.内容は以下の通りです.
Subを構築するときにsuperの構築方法を呼び出す理由と、Baseの構築方法でcallName()メソッドを呼び出す理由があるので、出力は親のbaseName、すなわち内容はbaseであり、Subを構築するときにsuperの構築方法を呼び出すが、Baseの構築方法でcallName()メソッドを呼び出す理由がある.ただし、サブクラスSubは親ベースのcallName()メソッドを書き換えているので、サブクラスのbaseName、すなわちsubとして出力されます.
私の分析はnullであるべきです.なぜですか.この類を少し改造すると以下のようになります.
1、まず、Baseのmain()メソッドのBaseb=new Sub()を実行する.文の場合、Subクラスに遭遇すると、JVMはSubクラスを先にロードしますが、それをロードするとextendsキーワードに遭遇するので、Subクラスをロードする前に親ベースをロードし、最初の行から出力された「親ベースの静的コードブロックが呼び出されました!」ちょうどこの点を検証した.
2、次に、Subクラスをロードする番になったので、2行目の出力は「サブクラスSubの静的コードブロックが呼び出された!」である.
3、そして、クラスのロードが完了し、new操作が実行されました.周知のように、new操作はオブジェクトをインスタンス化していますが、サブクラスがインスタンス化されると、親クラスの構築方法が呼び出されるのではないでしょうか.答えは肯定的で、3行目の出力結果も確かに「親ベースの構造方法が呼び出された!」
4、親ベースの構築方法では、親ベースのメンバー変数baseNameの値を出力し、出力した値もbaseである.
5.次に、callName()メソッドを呼び出します.では、このcallName()は親クラスを呼び出すべきですか、それとも子クラスを呼び出すべきですか.初期化されたサブクラスなので、サブクラスもちょうど親のcallName()メソッドを書き換えたので、結果はサブクラスを呼び出すcallName()メソッドに違いないが、5行目の出力結果も確かに「サブクラスSubのcallName()メソッドが呼び出された!」6、サブクラスのcallName()メソッドを呼び出す以上、サブクラスのbaseNameの値を出力すべきで、subではないでしょうか.まず関所を売って、次の出力を見てください.
7、7行目の出力結果は「サブクラスSubの構築方法が呼び出された!」何を説明しましたか.サブクラスcallName()メソッドを呼び出すと、サブクラスSubがインスタンス化されていないため、メンバー変数baseNameの値は「sub」ではなくnullしかないので、振り返って6行目の結果nullが出力されるのも不思議ではありません.
特に、サブクラスのメンバー変数baseNameをstaticと定義すると、結果は異なり、subとして出力されます.Subコンストラクションメソッドの実行前にサブクラスのcallName()メソッドが呼び出されますが、サブクラスメンバー変数baseNameがstaticとして定義されているため、サブクラスがJVMにロードされるとbaseNameの初期化が実行されます.出力結果は次のとおりです.
以上がその群友問題に対するすべての解答である.
次に、Javaの静的内部クラス、一般内部クラスなどの違いを簡単に振り返る:1、構造形式:静的内部クラスには2つの構造方式があり、1つ目は直接newの内部クラス名()であり、例えば上のBaseb=new Sub()であり、2つ目は外部クラスのクラス名に基づいている.内部クラス名()は、Baseb=new Baseのようなnew操作を行う.Sub();通常の内部クラスは、外部クラスを構成するインスタンスのみを表示し、外部クラスインスタンスを通過する.New内部クラス名()は、Baseb=new Base()のような内部クラスインスタンスを構築する.new Sub();
2、静的内部クラスは静的メンバーを持つことができ、静的内部クラスではなく静的メンバーを持つことができない.
3、静的内部クラスの非静的メンバーは外部クラスの静的変数にアクセスでき、外部クラスの非静的変数にアクセスできない.
4.非静的内部クラスの非静的メンバーは、外部クラスの非静的変数にアクセスすることができる.
未完待機!
public class Base {
private String baseName = "base";
public Base(){
callName();
}
public void callName(){
System.out.println(baseName);
}
static class Sub extends Base{
private String baseName = "sub";
public void callName(){
System.out.println(Sub.this.baseName);
}
}
public static void main(String[] args){
Base b = new Sub();
}
}
以上のBaseクラスのmain()メソッドは、いったい出力内容は何ですか?Subを構築するときにsuperの構築方法を呼び出す理由と、Baseの構築方法でcallName()メソッドを呼び出す理由があるので、出力は親のbaseName、すなわち内容はbaseであり、Subを構築するときにsuperの構築方法を呼び出すが、Baseの構築方法でcallName()メソッドを呼び出す理由がある.ただし、サブクラスSubは親ベースのcallName()メソッドを書き換えているので、サブクラスのbaseName、すなわちsubとして出力されます.
私の分析はnullであるべきです.なぜですか.この類を少し改造すると以下のようになります.
public class Base {
static {
System.out.println(" Base !");
}
private String baseName = "base";
public Base() {
System.out.println(" Base !");
System.out.println(" Base baseName " + baseName);
callName();
}
public void callName() {
System.out.println(" Base callName() !");
System.out.println(baseName);
}
static class Sub extends Base {
static{
System.out.println(" Sub !");
}
public Sub(){
System.out.println(" Sub !");
}
private String baseName = "sub";
public void callName() {
System.out.println(" Sub callName() !");
System.out.println(baseName);
}
}
public static void main(String[] args) {
Base b = new Sub();
}
}
Baseのmain()メソッドを実行すると、結果は何になりますか?答えは次のとおりです. Base !
Sub !
Base !
Base baseName base
Sub callName() !
null
Sub !
どうしてこんなことになったの?その概要を簡単に分析するには、次のようにします.1、まず、Baseのmain()メソッドのBaseb=new Sub()を実行する.文の場合、Subクラスに遭遇すると、JVMはSubクラスを先にロードしますが、それをロードするとextendsキーワードに遭遇するので、Subクラスをロードする前に親ベースをロードし、最初の行から出力された「親ベースの静的コードブロックが呼び出されました!」ちょうどこの点を検証した.
2、次に、Subクラスをロードする番になったので、2行目の出力は「サブクラスSubの静的コードブロックが呼び出された!」である.
3、そして、クラスのロードが完了し、new操作が実行されました.周知のように、new操作はオブジェクトをインスタンス化していますが、サブクラスがインスタンス化されると、親クラスの構築方法が呼び出されるのではないでしょうか.答えは肯定的で、3行目の出力結果も確かに「親ベースの構造方法が呼び出された!」
4、親ベースの構築方法では、親ベースのメンバー変数baseNameの値を出力し、出力した値もbaseである.
5.次に、callName()メソッドを呼び出します.では、このcallName()は親クラスを呼び出すべきですか、それとも子クラスを呼び出すべきですか.初期化されたサブクラスなので、サブクラスもちょうど親のcallName()メソッドを書き換えたので、結果はサブクラスを呼び出すcallName()メソッドに違いないが、5行目の出力結果も確かに「サブクラスSubのcallName()メソッドが呼び出された!」6、サブクラスのcallName()メソッドを呼び出す以上、サブクラスのbaseNameの値を出力すべきで、subではないでしょうか.まず関所を売って、次の出力を見てください.
7、7行目の出力結果は「サブクラスSubの構築方法が呼び出された!」何を説明しましたか.サブクラスcallName()メソッドを呼び出すと、サブクラスSubがインスタンス化されていないため、メンバー変数baseNameの値は「sub」ではなくnullしかないので、振り返って6行目の結果nullが出力されるのも不思議ではありません.
特に、サブクラスのメンバー変数baseNameをstaticと定義すると、結果は異なり、subとして出力されます.Subコンストラクションメソッドの実行前にサブクラスのcallName()メソッドが呼び出されますが、サブクラスメンバー変数baseNameがstaticとして定義されているため、サブクラスがJVMにロードされるとbaseNameの初期化が実行されます.出力結果は次のとおりです.
Base !
Sub !
Base !
Base baseName base
Sub callName() !
sub
Sub !
以上がその群友問題に対するすべての解答である.
次に、Javaの静的内部クラス、一般内部クラスなどの違いを簡単に振り返る:1、構造形式:静的内部クラスには2つの構造方式があり、1つ目は直接newの内部クラス名()であり、例えば上のBaseb=new Sub()であり、2つ目は外部クラスのクラス名に基づいている.内部クラス名()は、Baseb=new Baseのようなnew操作を行う.Sub();通常の内部クラスは、外部クラスを構成するインスタンスのみを表示し、外部クラスインスタンスを通過する.New内部クラス名()は、Baseb=new Base()のような内部クラスインスタンスを構築する.new Sub();
2、静的内部クラスは静的メンバーを持つことができ、静的内部クラスではなく静的メンバーを持つことができない.
3、静的内部クラスの非静的メンバーは外部クラスの静的変数にアクセスでき、外部クラスの非静的変数にアクセスできない.
4.非静的内部クラスの非静的メンバーは、外部クラスの非静的変数にアクセスすることができる.
未完待機!