読者です 読者をやめる 読者になる 読者になる

ローカルクラスの意義

Java Book

矢野勉さんの Wicket 本を買ってきて読んでいたんだけど、ちょっと気になる記述があった*1

MyDropDownChoice を定義している場所に注目してください。このクラスは HomePage クラスのコンストラクタの中で定義されています。このように Java ではメソッドの中でクラスを定義することも出来るのです。このようなクラスを「ローカル・クラス」と呼びます。
ローカルクラスの機能はほぼ匿名クラスと同じです。匿名クラスはローカルクラスの特殊な形態と考えることもできるでしょう。ローカル・クラスと匿名クラスの違いは、ローカル・クラスにはクラス名があるため、コンストラクタを定義できることです。

WicketによるWebアプリケーション開発 (P.113)

とあるんだけど、コンストラクタかどうかは別として、匿名クラス*2でもコンストラクタっぽいことは出来る*3

// このクラスの匿名クラスを作る
class BaseClass {
    private final String str;
    
    BaseClass(String str) { this.str = str; }
    
    @Override
    String toString() { return str; }
}

public final class Main {
    public static void main(String[] args) {
        final String arg = "hogehoge";
        BaseClass obj = new BaseClass("hoge") {
            // フィールド
            final String text;
            
            // インスタンスイニシャライザでコンストラクタ
            // インスタンスイニシャライザの評価はコンストラクタ起動の評価に含まれるため、
            // フィールドが final でも OK
            { text = arg; }
            
            @Override
            public String toString() { return super.toString() + text; }
        };
        
        System.out.println(obj.toString());
    }
}

こんな感じに、匿名クラスといえどフィールドは持てる*4し、コンストラクタっぽいことも出来る*5 *6
だから、ローカルクラスと匿名クラスの違いは、コンストラクタがどうとかにはないんじゃないかなー、と思うんだけどどうだろう。


じゃぁローカルクラスの意義ってなんなのさ、ってことになるけど、

  • 名前があるから複数回インスタンスが生成できる
  • 名前があるからスーパークラスから継承した以外のメソッドを定義して呼び出すことができる

の 2 点じゃないかな。まぁでもどっちも超特殊な状況でしか役に立たないんで、普通は匿名クラスで OK だろうけど。

*1:Wicket の入門本という意味ではすばらしい!みんな Wicket やればいいと思うよ

*2:Java の場合無名じゃなくて匿名で OK ですよね?

*3:インスタンスイニシャライザの評価はコンストラクタ起動の評価に含まれるから、ぽいことじゃなくて実際にコンストラクタと言えそうだけど、コンストラクタの定義とは違う気がするから「ぽいこと」って表現にとどめておく

*4:ClassInstanceCreationExpression は ClassBody を持てる。http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.9

*5:そもそも、本の中で紹介されてた状況 (スーパークラスのコンストラクタを同じ引数・順番で呼び出すだけ) なら、コンストラクタ呼び出しの引数に渡してあげればいいだけだけど

*6:出来るからと言ってやるべきかというと・・・