2011/10/21

Javaのよくわからない仕様

ちょっと落とし穴にはまったので備忘録。Java よりもテストコードが簡潔に書ける Processing で検証します。

まず、こちらをご覧ください。
Boolean b = Boolean.TRUE;  // TRUEで初期化した後に、
b = Boolean.FALSE;         // FALSEを代入する

なんの変哲もない、フラグの切り替えです。もちろんこれは、問題なく実行できます。

ところがこれ、List などのコレクションに集成すると、途端におかしくなる事に気付きました。

List<Boolean> boolList = new ArrayList<Boolean>();  // Booleanのリスト

  for(int i = 0; i < 10; i++) {
    boolList.add(Boolean.TRUE);     // 要素の初期化
  }

  boolList.get(0) = Boolean.FALSE;  // 代入(ここでエラー)
//~~~~~~~~~~~~~~~

これを実行すると、こんなふうに怒られちゃいます。
The left-hand side of an assignment must be a variable
えー、なんでー。

これじゃあフラグを切り替えられないじゃん!!

※ 余談ですが、『フラグをリストに格納する』というシチュエーションは、グラフアルゴリズムなどで活躍します。



実は、Boolean に限らず、コレクションの get() メソッドで取得したオブジェクトに代入しようとすると上記の現象が発生するようです。……にも拘わらず、今までこの問題を意識した事はありませんでした。

というのも、普通は、
Hoge h = hogeList.get(i);
のように、一旦 Hoge 型の変数 h にオブジェクトを代入して、h 経由でメソッドを呼んだりフィールドをいじったりできるため、『リストの特定の要素を全く別のオブジェクトで上書きしたい』という発想自体がそもそも無かったわけです。

ところが、Boolean クラスはたいへん素性の悪いもので、Java の公式ドキュメントを見ても状態を変更するメソッドが見当たりません。

そこで、スイッチしたいフラグを List#get() メソッドで取ってきて、そこへおニューのオブジェクトを代入しようという力技を思いついたのですが、まぁ前述の通りうまく行かず途方に暮れた次第であります。



【解決篇】

あれこれ悩んで Java が嫌いになりかけた頃、試しに List#set() メソッドを使ってみたら超呆気なく解決しました。なんだこれ。

List<Boolean> boolList = new ArrayList<Boolean>();  // Booleanのリスト

for(int i = 0; i < 10; i++) {
  boolList.add(Boolean.TRUE);     // 要素の初期化
}
  
boolList.set(0, Boolean.FALSE);  // 置換(これでうまくいく)

やったね。ねむい。

0 件のコメント:

コメントを投稿

ひとことどうぞφ(・ω・,,)