凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 6541
  • トラックバック - 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
コメント
  • # re: 内部クラスの階層
    かつのり
    Posted @ 2007/07/31 23:22
    非staticの内部クラスのコンストラクタには昔泣かされた覚えが・・・
    勝手に第一引数に自動的にトップレベルの型が追加されるんですよね。
    リフレクションでどうやっても取得できなくて、
    列挙したらあれれ・・・?みたいな感じで納得しましたよ。
  • # re: 内部クラスの階層
    じゃんぬねっと
    Posted @ 2007/07/31 23:32
    私は this.new 派ですよ。
  • # re: 内部クラスの階層
    凪瀬
    Posted @ 2007/08/01 0:10
    リフレクションはラーの鏡ですからねぇw
    inner class周りは知らない人も多いようなのでもうちょっと補足していきたいところです。

    オブジェクト指向分科会#1のときに、オブジェクト指向的な意味でnewの主語は誰になるんだ!?という話題がありまして、エンクロージング型のnewのときのthis.newだと主語が明確だなぁということを考えていたのでした。
    そのあたりの話題がぼけてしまっていますね。もっと話の流れを明確にしないといけません。blogは勢いで書いているけど、もうちょっと文章を練った方がよいのかな。
  • # re: 内部クラスの階層
    裏口
    Posted @ 2007/08/01 0:44
    相変わらず濃いなあ。
    # たまには普通のカクテル出してくださると嬉しいけどw
  • # re: 内部クラスの階層
    じゃんぬねっと
    Posted @ 2007/08/01 10:33
    >nagise さん
    文章を練りたければ練れば良いでしょうけど、苦痛に感じるこおがあれば元も子もないので今のままの方が良いと思いますよ。やはり Blog 疲れ状態にならないようにしないといけませんよね。

    >裏口さん
    いえいえ、このあたりはコードを書くサイドに立った基本形なネタですよ。設計者側からするとどうでも良いことかもしれませんが、プログラマ側の責任者としては 1 番細かく意識したいところです。
  • # re: 内部クラスの階層
    凪瀬
    Posted @ 2007/08/01 10:52
    クラス設計は難しい課題ですからね。
    一発で成功するのは殊更難しい…。
    だからこそリファクタリングを重ねつつすり合わせていくのかもしれません。

    内部クラスはうまく活用すればコードがすっきりするのですが、設計に生かせるようになるまでは苦労の多い代物なんですよね。具体的な使い方を示唆するほうがいいのかな。
  • # 内部クラスの使いどころ
    凪瀬 Blog
    Posted @ 2007/08/01 23:31
    内部クラスの使いどころ
  • # re: 静的メンバの使い道
    .COM -どっとこむ-
    Posted @ 2007/08/06 17:47
    re: 静的メンバの使い道
  • # radio
    bogemi
    Posted @ 2011/08/26 9:13

    http://www.buysale.ro/anunturi/auto/masini-si-echipamente-agricole/iasi.html - iasi
タイトル  
名前  
Url
コメント