Unknown Region

プログラムでハマったエラーとその解決方法についての備忘録メモ

【Java】Mapへの初期代入について

JavaでMapを作成して最初に何か値を代入したい場合、通常は以下のようにすると思います。

 

Java8でのHashMapの生成と代入例:

Map<String, String> map = new HashMap<>();
map.put("hoge", "fuga");
map.put("foo", "bar");

ただ、他の言語を触っている人だと、Mapの作成と同時に値を設定して置きたいと感じるのではないでしょうか。

例えば下のコードのような形です。

 

PerlでのHash(連想配列)の生成と初期代入例:

my %map = ('hoge' => 'fuga', 'foo' => 'bar');

これをJavaでやろうとすると以下のようにすることで実現できます。

 

Java8でのHashMapの生成と初期代入例:

Map<String, String> map = new HashMap<String, String>() {{
  put("hoge", "fuga");
  put("foo", "bar");
}};

ただしJavaでこの方法を使う場合、一点だけ注意が必要です。

それは、mapのインスタンスの実クラスがHashMapではなくHashMapを継承した匿名クラスになってしまうということ。

どういうことかを説明するために、上記のコードを匿名クラスを使わない書き方に変更すると次のようになります。

 

Java8でのHashMapの生成と初期代入例(匿名クラスを使わない):

class ExtendedHashMap extends HashMap<String, String> {
  {
    put("hoge", "fuga");
    put("foo", "bar");
  }
};
Map<String, String> map = new ExtendedHashMap();

ではこれで何か不都合が起こるかという話なのですが、map.getClass()などでクラスの情報を取るような場合に思った通りのクラス名が取得できないというデメリットがあります。

実際に「Java8でのHashMapの生成と初期代入例」のプログラム実行後に、map.getClass().getName()を取得してみると「プログラム名$1」という結果が返ってくるはずです。

自分の組んだプログラム内では問題がなくても、フレームワークや外部モジュールの作りによっては、もしかしたらここが落とし穴になるかもしれませんね。