Java static クラス

いまのところ、「Google Androidアプリケーション開発入門 画面作成からデバイス制御まで――基本機能の全容」 を教科書としてサンプルを実装したりしてるのですが、SQLite のサンプルで、インナークラスを static 宣言してるんですね。

Google のチュートリアルでも同様でした。

ちょっと、見慣れない記法だと思ったのですが、どう使い分けるのだろう?

ちょっと挙動を試してみました。

static_class

Bar クラスと、Foo クラスを作成。

Barクラス

package test;

public class Bar {
    private String m_str;
    public Bar() {
        m_str = "Bar";
    }
    class Ham {
        public String getValue() {
            // 外部クラスの静的でないメンバーが参照できる
            return "Ham | " + Bar.this.m_str;
        }
    }
    static class Spam {
        public String getValue() {
            // ② 外部クラスの静的でないメンバーは参照できない
            // return Bar.this.m_str;
            return "Spam";
        }
    }
    
    public void makeInstance() {
        // ① 同じようにインスタンスは作れる
        System.out.println(new Ham().getValue());
        System.out.println(new Spam().getValue());
    }
}

Fooクラス

package test;

public class Foo {
    public static void main(String[] args) {
        
        // ③ クラスからインスタンス化できない。インスタンス化してから
        // Bar.Ham h = new Bar.Ham();
        Bar.Ham h = new Bar().new Ham();
        
        // ④ クラスからインスタンス化できる
        // Bar.Spam s = new Bar().new Spam();
        Bar.Spam s = new Bar.Spam();
        
        System.out.println(h.getValue());
        System.out.println(s.getValue());
        
        new Bar().makeInstance();
    }
}

結果

Ham | Bar
Spam
Ham | Bar
Spam

 

static クラス なので、なんか、インスタンスが作れない!? みたいに思ってしまうが、そんなことはない。

それぞれ、アウタークラスから、インナークラスのインスタンスは作成できる。(①)

ただし、当たり前と言えば当たり前だが、sutatic クラスからは、アウタークラスの static でないメンバー変数にアクセスできない(②)

Bar のインナークラスの、Ham と Spam のスコープ指定をしていないので、同一パッケージからは参照できる。

それぞれ、を同一パッケージの Foo クラスから参照してみる。

static でないインナークラスをアウタークラス以外のクラスからインスタンス化するには、アウタークラスをインスタンス化する必要がある。(③)

しかs、static なインナークラスは、アウタークラス以外のクラスからインスタンス化するには、static メソッドを参照するのと同じ仕方でインスタンス化できる。(④)

staticのついた内部クラスは、パッケージのように使える」 とはそういう(④)意味か。

ちょっとしたクラス群をパッケージではなくて、クラスにまとめて使うには、有用そうだ。これが使い方の本命かしら。

static でない場合の書き方、

new Bar().new Ham();

これは、覚えにくいし、違和感あるが、

new Bar.Spam();

こっちの書き方なら自然だ。