2009年12月12日土曜日

[Java]Calendarクラスは可変オブジェクト

StringやBigDecimalオブジェクトといった所謂『不変オブジェクト』を使っていて、「値が変わらない!」と嘆いたことは、大抵1度くらいは経験した事があると思う(ベテランになってもたま~にやってしまう…)。特に、C言語のポインタの例でよく出てくる、以下のように引数の値を変更する例。

メソッド呼出元の値をメソッド内で書き換えるという作りは宜しくないと思うので、この『不変オブジェクト』という概念はナイスだと思います。引数をメソッド内で弄り倒しても、呼出元の値は何の影響も受けない。
そういうわけで、不変オブジェクトに慣れてくると、何の躊躇も無しに引数をメソッド内で弄り倒してしまいがちです。しかし、『不変オブジェクト』と言われる以上、当然『可変オブジェクト』も存在します。この可変オブジェクトを不変オブジェクトと同じ感覚で弄り倒してしまうと、後で血ヘドを吐く事になりかねませんので、注意が必要です。はい、先月の僕がそうでした(いや、すぐに気付きましたけど…)。

先月の僕が遭遇した可変オブジェクト、それはCalendarクラスです。Calendarインスタンスを引数で渡し、引数と同じ年月・日付はその年月の月末日であるCalendarインスタンスを返すというメソッドを作成しました。初版のソースは以下。


ホント馬鹿です。正しくは以下でした。


不変オブジェクトと可変オブジェクトの見分け方は、そのインスタンスの値を弄くるメソッドの戻り値の有無で大体判別できると思いますが、どうなんでしょう。ていうかドキュメント読めって話ですが。

戻り値有り:不変オブジェクト
戻り値無し:可変オブジェクト


※「値を弄くる」ことができないのが不変オブジェクトなので、上の言い方は適切ではありませんが…

いやはや、前回のBigDecimalといい、4年目にして今更こんな事言っているようじゃ、やっぱり俺まだまだ初級だわ。細かい処理がラッピングされた、某フレームワークのライブラリでばかり組んできたので、基本が抜けてしまっている。フレームワークの功罪というやつか?(勉強不足と言われたら、返す言葉も無いですが…)

おまけというか個人的メモ

月末日付取得
getActualMaximumを利用。Calendar.DATEを引数に指定する事で、その年月が取り得る日付の最大値、つまりその年月の月末日付を返す。使い方は上の例を参照。
日付間日数取得
Calendarオブジェクトが内包しているDataオブジェクトを利用する。Date#getTime()で1970/1/1 00:00:00(GMT)からのミリ秒数を取得できるので、これの差分を日単位に変換すればよい。尚、Date#getTime()の戻り値long型。

0 件のコメント: