1. ホーム
  2. Java

XXX型を囲むインスタンスがJavaでアクセスできない

2022-02-12 05:32:55

Javaコード作成時に、mainメソッドで内部クラスのインスタンスを作成する際に、コンパイル段階でエラーが発生する問題が発生しましたので、エラー解説をご覧ください。

この行に複数のマーカーがある
 - ローカル変数testの値は使用されていない
 - StaticCallDynamic 型の包含するインスタンスにアクセスできない。StaticCallDynamic 型の包含インスタンスで割り当てを修飾する必要があります (例 : . 
  x.new A() は、x が StaticCallDynamic のインスタンスである場合)。

確認したところ、インナークラスは dynamic(staticキーワード修飾子なし)、mainメソッドは static なので、通常のインナークラスオブジェクトはそれを生成したアウタークラスオブジェクトへの参照を暗黙的に保持しており、staticメソッド(クラスのロード時に初期化)でインナークラスを呼び出すには、まずアウタークラスを生成する必要があることがわかりました。つまり、次のように作成します。 "DanymicTest test = new StaticCallDynamic().new DanymicTest();" ここでStaticCallDynamicは外部クラス、DanymicTestは内部動的クラスです。 内部を静的クラスに変更すれば、mainで直接内部クラスのインスタンスを作成することができます。

  ところで、スタティックメソッドからダイナミックメソッドの呼び出しについて見てみると、print()がクラス内のダイナミックメソッドであるところ、スタティックメソッドを直接呼び出した場合、次のような問題が発生します。

StaticCallDynamic型から非静的メソッドprint()への静的参照はできません。

  これは、javaのメモリの仕組みの観点から分析する必要があります。まずオブジェクトをNewするとき、ヒープにオブジェクト用のメモリ空間を確保するのではなく、クラスのスタティックメソッド(static修飾子をつけたスタティック関数)のコードをメソッド領域というところにロードして、ヒープメモリにオブジェクトを生成します。つまり、クラスの読み込みと同時にスタティックメソッドも読み込まれるということですね。オブジェクトをnewすると、そのオブジェクトはメモリの対に存在し、thisキーワードはそのオブジェクトを指すのが一般的ですが、オブジェクトをnewせず、クラス名でそのクラスのスタティックメソッドを呼び出しても問題ないでしょう。

  クラスの静的メンバ(変態やメソッド)はクラスそのものに属し、クラスのロード時にメモリが確保され、クラス名で直接アクセスできますが、非静的メンバ(変数やメソッド)はクラスのオブジェクトに属し、クラスのオブジェクトの生成時(インスタンス生成時)だけメモリを確保し、クラスのオブジェクトでアクセスすることができます。クラスの静的メンバの中にある非静的メンバにアクセスすると間違うことがあるのは、クラスの非静的メンバが存在しないのに静的メンバが既に存在するため、メモリ上に存在しないものにアクセスすると間違うことがあるからです。

  そのため、メソッドもスタティックメソッドに変更するか、メソッドが存在するインスタンスを生成してインスタンス経由で呼び出すかのどちらかになります。