質問: new Sample(); s.test(); //staticなmainメソッドから非staticなtestメソッドを呼び出しているのでは? } } public class Sample { void test(){ System.out.println("A"); } }
回答: 「staticなメソッドから非staticなメソッドへのアクセスはできない」という説明は、正確には「staticなメソッドから、(同一クラス内の)非staticなメソッドへの(直接の)アクセスはできない」という意味です。 したがって、以下の例のように、staticなxメソッドから、同じAクラス内の非staticなyメソッドへの直接のアクセスはNGでありコンパイル・エラーとなります。 ``` class A { static void x() { // static y(); // 直接アクセス: NG } void y() { // 非static // 何らかの処理 } } ``` では、直接でなければOKというのはどういうことかというと、そのクラスのインスタンスを生成して間接的に(インスタンスを介して)アクセスすることは問題ないということです。 ``` class A { static void x() { // static A a = new A(); // このクラスのインスタンスを生成 a.y(); // インスタンスを介した間接的なアクセス: OK } void y() { // 非static // 何らかの処理 } } ``` クラス内に宣言されたメソッドの実行方法には、大きく分けて以下2つの方法があります。 1. インスタンスを生成することなく、クラスに属するメソッドとして実行 2. クラスからインスタンスを生成し、インスタンスに属するメソッドとして実行 1番の方法で実行するためのメソッドが「staticメソッド」です。そして2番の方法で実行するメソッドが「非staticメソッド」となります。非staticメソッドは必ずインスタンスを生成して呼び出す必要があることから「インスタンス・メソッド」とも呼ばれます。 これら2つのメソッドは1つのクラス内に混在させることができるため、同じクラスを利用する場合でも呼び出すメソッドによって「インスタンスを生成しなくてもよいのか(staticメソッド)」、それとも「インスタンスを生成しなければならないのか(非staticメソッド)」が決定します。 先ほどの例のAクラスでは、xメソッドはstaticメソッドであるため、Aクラスのインスタンスを生成することなく呼び出すことができます。反対にyメソッドは非staticメソッドであるため、必ずインスタンスを生成して呼び出す必要があります。少し乱暴に言い換えれば、xメソッドはクラスにのみ存在するメソッド、yメソッドはインスタンスにのみ存在するメソッドと考えることができます。 Javaのプログラムを実行する際に、クラスは常に存在していますが(使用に先立ってメモリにロードされます)、インスタンスはnewを使用して明示的に生成しない限り存在しません。 ここで、xメソッドはAクラスのインスタンスが存在していなくても使用できるという仕様になっているのに(staticだから)、そのxメソッド内の処理において、Aクラスのインスタンスが存在していなければ呼び出すことのできないyメソッドを呼び出すコードを書けてしまうとおかしいですよね? ルールに矛盾することになります。したがって、1番目の例はNGになるということです。 しかし、2番目の例では、xメソッドの処理の中でAクラスのインスタンスを生成しているため、そのインスタンスを介してyメソッドを呼び出すことができているわけです。 質問者さんが提示しているコードも同じですよね。 なぜこのようにstaticと非staticの2種類があるかというと、1つは設計上の観点。インスタンスは固有のデータを持ち、その固有のデータに基づく処理を担います。もしインスタンスに共通のデータや処理があるなら、それはインスタンスごとに持たせるのではなく、クラスで共用すればいいですよね? それがstaticなメンバーです。 もう1つは処理性能とメモリの効率的な利用というハードウェアの観点からです。インスタンス生成はメモリのヒープ領域に動的にデータを割り当てるという比較的重たい処理となります。また、インスタンスを作れば作るほどメモリの領域を使用することになります。先に書いたように、インスタンスごとに必要ないデータや処理があるのであれば、わざわざインスタンスを作る必要はなく、ロードされたクラスのまま実行すればいいですよね? Javaのプログラムがメモリにどのようにロードされて実行されるのかも勉強すると、もっと深く理解できると思います。