凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 47539
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

本日のカクテルは Enclosing Inner Classです。
日本語ではエンクロージング内部クラスなどといわれます。 Javaの内部クラスはいくつか種類があり、宣言とインスタンス生成の仕方は以下のようになります。

public class Outer {
  /** staticな内部クラスの宣言 */
  public static class StaticInner { }

  /** エンクロージング内部クラスの宣言 */
  public class EnclosingInner { }

  public static void main(String[] args) {
    // ローカル内部クラスの宣言
    class LocalInner { }

    // staticな内部クラス
    StaticInner staticInner = new StaticInner();

    // エンクロージング内部クラス
    Outer outer = new Outer();
    EnclosingInner enclosingInner = outer.new EnclosingInner();

    // ローカル内部クラス
    LocalInner localInner = new LocalInner();

    // 無名クラス
    Runnable runnable = new Runnable() {
      public void run() {
      }
    };
  }
}

今回はこのうちエンクロージング型に絞って話をしましょう。

Outer.javaファイルの中にはOuterクラスが宣言されます。javaファイルにはファイル名と同じクラスが宣言される。これは基本ですね。 内部クラスは、これらトップレベルクラスの内側に宣言されるのです。

エンクロージング型の内部クラスの特徴はOuterクラスのインスタンスと結びつきがあるということです。 newするときには、newの前に外側のクラスのインスタンスを書きます。 あたかもOuterクラスのメソッドのような扱いですね。newの主語はOuterのインスタンスなのです。
ちなみに、Outerクラスのインスタンスメソッド内でエンクロージング内部クラスをnewする場合は

  public void hoge() {
    EnclosingInner enclosingInner = this.new EnclosingInner();
  }

というようにthis.new となります。
そしてthisは省略可能ですから

    EnclosingInner enclosingInner = new EnclosingInner();

というようになります。ですから、省略しない書き方を知らない人が結構いますね。

このエンクロージング内部クラスの内側からはnewするときに指定したOuterクラスのインスタンスが参照できます。 単一のOuterクラスを元に、複数エンクロージング内部クラスのインスタンスを生成すると、まるでstaticフィールドのごとく、 同一のOuterクラスのフィールドが見えるのです。

public class Outer {
  public int outerParam;

  /** エンクロージング内部クラスの宣言 */
  public class EnclosingInner {
    private int innerParam;

    public void hoge() {
      // Outerクラスのフィールドを参照
      System.out.println(Outer.this.outerParam);
      // Innerクラスのフィールドを参照
      System.out.println(this.innerParam);
    }
  }
}

この1対多のオブジェクトの関係は、まるでClassとインスタンスの関係のようですね。

シャノンさんのオブジェクト≠インスタンスという記事では Javaのクラスそのものがインスタンスなのだ、という話がされています。 staticというのはエンクロージング内部クラスにとってのOuterクラスのような存在なのですね。
トップレベルのクラスのnewの主語はこのjava.lang.Classのインスタンスになるのですね。 そして、java.lang.Classのインスタンスというのは通常は単一なのですが、ClassLoaderが変わると別物として振舞うのです。 違うClassLoaderでロードされたClassというのは、同じ型の別インスタンスのような関係になります。

Javaのオブジェクト指向はこのような階層構造を持っている、ちょっと拡張された概念のようです。

投稿日時 : 2007年7月31日 23:05
コメント
タイトル
名前
Url
コメント