読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

インスタンスイニシャライザ

インスタンスイニシャライザを指定すると、クラスのインスタンス生成時に特定の処理を行うことができます。

  • クラスの直下( class Hoge { /*ここ*/ } )に「{<処理>;...}」の形式で書きます。
    • スタティックイニシャライザと同じノリですね。
  • 指定した処理は、オブジェクトを生成する時「コンストラクタの前」に実行されます。
  • イニシャライザのブロック中では、「this」が利用でき、省略も可能です。

サンプル。

/**親クラス*/
private static class Animal {
    Animal() {
        System.out.println( "initialize animal." );
    }
    // 親のインスタンスイニシャライザ
    {
        System.out.println( "instance initializer parent." );
    }
}
/**派生クラス*/
private static class Kitten extends Animal {

    // インスタンスイニシャライザ1
    {
        System.out.println( "instance initializer 1." );
    }
    // インスタンスイニシャライザ2
    {
        System.out.println( "instance initializer 2." );
    }
    Kitten() {
        System.out.println( "initialize kitten." );
    }
}

/**
 * メイン
 * @param args 引数
 */
public static void main ( String[] args ) {
    new Kitten();
}

実行結果です。

instance initializer parent.
initialize animal.
instance initializer 1.
instance initializer 2.
initialize kitten.

使いどころ

次のようなメンドクサイクラスを使うはめになった時、これを使うとスマートに書けそう!と思いました。
まずは、インスタンスイニシャライザを使わない場合。

LocationConditionsDomain locationConditions = new LocationConditionsDomainImpl();

List<LocationConditionDomain> tmp = new ArrayList<LocationConditionDomain>(3);

LocationConditionDomain locationCondition = new LocationConditionDomainImpl();
ObjectIdentityDomain objectIdentity = new ObjectIdentityDomainImpl();
objectIdentity.setId( "hoge" );
locationCondition.setObjectIdentity( objectIdentity );
tmp.add( locationCondition );

locationCondition = new LocationConditionDomainImpl();
objectIdentity = new ObjectIdentityDomainImpl();
objectIdentity.setId( "foo" );
locationCondition.setObjectIdentity( objectIdentity );
tmp.add( locationCondition );

locationCondition = new LocationConditionDomainImpl();
objectIdentity = new ObjectIdentityDomainImpl();
objectIdentity.setId( "var" );
locationCondition.setObjectIdentity( objectIdentity );
tmp.add( locationCondition );

locationConditions.setDepth( DepthDomain.INFINITY );
locationConditions.setList( tmp );

コンストラクタで引数を受け付ける設計になってないので、ちまちまsetしていかないといけません。メンドイ。

ここで、インスタンスイニシャライザを使うと次のように書けます!

LocationConditionsDomain locationConditions = new LocationConditionsDomainImpl() {{
    setDepth( DepthDomain.INFINITY );
    setList( new ArrayList<LocationConditionDomain>(3) {{
        add( new LocationConditionDomainImpl() {{
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("hoge"); }} );
        }} );
        add( new LocationConditionDomainImpl() {{
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("foo"); }} );
        }} );
        add( new LocationConditionDomainImpl() {{
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("var"); }} );
        }} );
    }});
}};

Listの生成はArraysの方が好きだな。

LocationConditionsDomain locationConditions = new LocationConditionsDomainImpl() {{
    setDepth( DepthDomain.INFINITY );
    setList( Arrays.asList( new LocationConditionDomain[] {
        new LocationConditionDomainImpl() {{ 
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("hoge"); }} );
        }} ),
        new LocationConditionDomainImpl() {{ 
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("foo"); }} );
        }} ),
        new LocationConditionDomainImpl() {{ 
            setObjectIdentity( new ObjectIdentityDomainImpl() {{ setId("var"); }} );
        }} )
    }));
}};

こんな感じ。最初のと比べるとだいぶスマートかと。オブジェクトの階層が一目でわかるのがいい。

で、気になるのは次の3点。

  • 匿名クラスでインスタンスイニシャライザを追加する方法なので、イニシャライザで使う引数はfinalでないといけない。このせいで使いにくい場面はありそう。
  • クラスがfinalの場合使えない。(当たり前)
  • あと、匿名クラスを使うことによるオーバーヘッドがないかも気になるところ。今度測ってみよう。


参考:JavaA2Z - インスタンス初期化子