クラスの遅延初期化方法

普通、シングルトンなクラスを作るとき、ふつう初期化は以下のようにする

    public class Hoge {

        private static final Hoge hoge = new Hoge();

        private Hoge() {}

        public static Hoge getInstance() {
            return hoge;
        }

    }

でも、これだとクラスHogeを参照しただけでインスタンスが作成されてしまって、必要ない場合でもインスタンスが構築されちゃっていやだなあ、遅延初期化出来ないかなあ、と思っていたところ、以下のような書き方があることを知った。

    public class Hoge {

        private static class HogeHolder {
            static final Hoge hoge = new Hoge();
        }

        private Hoge() {}

        public static Hoge getInstance() {
            return HogeHolder.hoge;
        }

    }

なるほど!

これなら最初にgetInstance()を呼ぶまでインスタンスは生成されず、必要になってからインスタンスが生成される。

これはいい勉強になった。

Vista で DHCPサーバーからIPを取得できない…

この正月の話。

実家に帰省したとき、妹が実家の無線LANルーターの設定をいじってて、とても心の広い設定*1になっていたのに怒りを覚え、引き篭もり設定*2と変更した。
このとき、無線LANルータールーターモードになっていたのでこれをブリッジモードに変えたところ、妹のVistaマシンが急に無線LANに接続できない!という状態になった。

どうも、DHCPからIPアドレスが取得できないという状態のようだった。

ブリッジモードをルーターモードにすると、ちゃんとIPアドレスが取得できる。
そして、XPではブリッジモードでも問題なく動作する。

帰省していた間ずっと調査して*3、結局ルーターモードで運用するようにして実家を去った。

妹には役立たず呼ばわりされ、嫁さんは怒り、あの日の忸怩たる思いはいまでも忘れない。

あの日自分を苦しめた現象の原因が、ようやくわかった。
多分これだ。↓
Windows Vista で特定のルーターやマイクロソフト製以外の特定の DHCP サーバーから IP アドレスを取得できない

実家の無線LANルーターは多分これなんだけど、これはVistaに対応しているけど、フレッツ光で使ってるルーターDHCP機能はVistaに対応していないんじゃないだろうか。だから、ルーターモードだと正しく動作して、ブリッジモードだと駄目だったのでは。

こんど実家に行くことがあったら試してみよう。

*1:WEP-64bit

*2:WAP-AES

*3:嫁さんをほったらかしにしていたらかなり怒られた

クラス継承での注意事項

継承クラスでコンストラクタが呼ばれる順番は以下の通り

  1. 親クラスのコンストラクタ実行
  2. 子クラスの変数初期化
  3. 子クラスのコンストラクタ実行

なので、以下のような抽象クラスを作ってしまうと、正しく動作しない

public abstract class hoge { 
    public hoge(){
        PrintMessage(); <- ここで抽象メソッドを呼ぶ
    }
    protected abstract void PrintMessage(); <- この実装は子クラス
}

public abstract class hogehoge extends hoge { 
    public hogehoge(){
        super();
        //↑この中で「PrintMessage」メソッドが呼ばれるが、この時点ではまだ継承クラス変数の
        //初期化が終わっていない為、システムアウトには「null」と出力される
    }
    private String s = "TESTMESSAGE";
    protected void PrintMessage(){
        System.out.println(s);
    }
}

気をつけよう。

レコード型変数の初期化

Delphiで、レコード型変数に宣言時に初期値を入れる方法がわかったのでメモ。

type
  TTestRec = record
    column1: String;
    column2: String;
    column3: String;
  end;

var
  //宣言時にデフォルト値入力
  var_t: TTestRec = (column1:'VAR1'; column2:'VAR2'; column3:'VAR3' );

const
  //定数値で値を入れる
  const_t: TTestRec = (column1:'VAR1'; column2:'VAR2'; column3:'VAR3');

かっこいいfor文

ツリー構造を、ノードからルートまでたどって処理をするプログラムを書くとき、いままでは以下のように書いていた。

		Node nd = currentNode;
		while(nd != null) {
			queue.add(nd);
			nd = nd.parent();
		}

今日、本を読んでいたら、以下のように書かれているのを見つけた

		for(Node nd = currentNode; nd != null; nd = nd.parent())
			queue.add(currentNd);

すごくシンプルでかっこいい!
結局は同じことなんだけれど、ループを制御する文とループ内で行う処理がきれいに2文で書かれていていい。
for命令の中で親ノードを代入するってのは思いつかなかった。

今度同様の処理を書く機会があったらこんな風に書いてみよう