- PR -

インナークラスのstaticメソッド

1
投稿者投稿内容
akamax
会議室デビュー日: 2002/10/11
投稿数: 3
投稿日時: 2002-10-16 13:36
こんにちは。目下SJC-Pに向け勉強中のサンデープログラマーです。

さて、ネストされたクラスのサンプルをあれこれ作りながら
勉強しているうちに、コンパイルが通らない壁にぶち当たって
しまったので質問させて下さい。

インナークラスがクラスフイールドはもつことが許されるが
クラスメソッドが許されないのは何故なのでしょうか?

言葉ではちょっとわかりにくいかも知れませんので
しょうもない(汗、サンプルを載せます。

class Outer {
  private final String name = "Outer";

  void foo() {
    System.out.println( "My name is " + name );
  }

  // staticネストクラス
  class Inner {
    private final static String name = "Inner"; // クラスフィールドはOK
    public static void foo() { // クラスメソッドはNG。何故??
      System.out.println( "My name is " + name );
    }
  }

}

// テスト用のクラス(ネストクラスを外から使うのは本筋ではないけど...)
class TestNestedClass {
  public static void main( String[] args ) {
    Outer out = new Outer();
    out.foo();

    Outer.Inner in = out.new Inner();
    in.foo();
  }
}

この場合、TestNestedClassから、Innerへのクラスメソッドを使うには
Innerクラスがstaticではないのでthis経由でしかアクセスできない
はずですから、

  Outer.Inner in = out.new Inner();
  in.foo();

となりますが、それ以前に Innerクラスのクラスメソッド

  public static void foo()

がコンパイルエラーとなってしまいます。
Innerクラスがクラスメソッドをもつこができないのは何故でしょうか?
エンクロージングでしか利用しないことも考えれば、インナークラスが
クラスメソッドを持てないのは疑問です。

よろしくお願いします。
BBC
常連さん
会議室デビュー日: 2002/03/15
投稿数: 37
お住まい・勤務地: 東京
投稿日時: 2002-10-16 15:28
こんにちは。
インナークラスについて、少し探したら以下の文書を見つけました。
・インナークラス
http://gimlay.org/~javafaq/S016.html#S016-03
・利用方法
http://gimlay.org/~javafaq/S016.html#S016-09
つまりstaticでない=インスタンス化必須な上、
自身に操作可能なクラス変数が存在しないので、
クラスメソッドを定義する事に意味が無いのです。

#static finalは定数として扱われるのでOKなのです。

そもそもインナークラスは上記のURL内の説明にもあるように、
・外側のクラスと非常に結びつきの強いオブジェクトである
・独立したオブジェクトとして宣言してもあまり意味がない
といった要件のために定義されているようです。

>エンクロージングでしか利用しないことも考えれば、インナークラスが
>クラスメソッドを持てないのは疑問です。

外側のクラスのローカル変数を操作をする事を主な目的としているので、
自身のクラス変数のみの操作しか出来ないクラスメソッドは、
存在意義が無いと思うのですが・・・。
static な変数やメソッドが必要な場合は、裏を返せば独立性が高いという事なので、
独立したクラスとして宣言しなさいという事なのでしょう。

#うーむ、まとまりが無い文章だ・・・。

[追記]
staticな変数もコンパイルエラーになります。
エラーにならなかったのは、定数化されていたからです。

[ メッセージ編集済み 編集者: BBC 編集日時 2002-10-16 15:41 ]

[ メッセージ編集済み 編集者: BBC 編集日時 2002-10-16 20:13 ]
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-10-16 19:41
コード:
public class TopClass {

    ... 略 ...

    class InnerClass {
        //staticなメソッド       <- コンパイルエラーになる。
        static void staticMethod() {
        }
    }
}



ちょっと考えてみてください。上記の例だと、InnerClassは TopClassのインスタンスからでないとアクセスできません。ためしに、以下のようなコードを書いてコンパイルするとエラーになります。

コード:
public class TopClass {

    public static void main(String[] args) {
        InnerClass in = new InnerClass();  // <- ここでコンパイルエラーになる。
    }
    ... 略 ...

    class InnerClass {
    }
}


このコンパイルエラーは、staticなmainメソッドから非staticなInnerClassにアクセスしようとするからです。つまり、インナークラスであるInnerClassはTopClassのインスタンスが生成されない限りアクセスできないわけです。staticなメソッドやフィールドを使用する利点はインスタンスを作る必要がないということですから、TopClassのインスタンスを作らないとアクセスできないインナークラスのstaticなメソッドやフィールドは意味がありません。

ですからJava言語仕様で
引用:

http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#262890 から引用:
An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

http://www.y-adagio.com/public/standards/tr_javalang2/classes.doc.html#262890 から引用:
部クラス(inner class)は,明示的又は暗黙にstaticと宣言されない入れ子クラスとする。内部クラスは,静的初期化子(8.7)又はメンバインタフェースを宣言してはならない。内部クラスは,コンパイル時定数フィールド(15.28)でない限りは,静的メンバを宣言してはならない。


と定められています。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-10-16 22:30
引用:

akamaxさんの書き込み (2002-10-16 13:36) より:

インナークラスがクラスフイールドはもつことが許されるが
クラスメソッドが許されないのは何故なのでしょうか?



ちょっと補足。
上記した言語仕様の引用の通り、インナークラスが持つことがstaticな物で許されているのは static final な定数のみです。staticなフィールド(クラスフィールド)はstaticなメソッド(クラスメソッド)と同様で持てません。

static final int CONSTANT = 0; //<-これはOK
int var = 0; //<-これはOK

static int var = 0; //<-これはNG
1

スキルアップ/キャリアアップ(JOB@IT)