JavaでIntegerからStringへのキャストはClassCastException。例と解法。
当然と言えば当然なのですが、JavaのIntegerからStringへキャストする部分でClassCastExceptionが発生しました。
さも当然、常識の様に書き始めましたが、実は「あれ?そうだっけ??」と思って調べまくってしまいました。でもJava 8 Gold 保持者としては「当然でしょ?」としらをきるしかありません(^_^;)
原因のコードを要約して紹介
仕事で出会ったそのコード、いろいろ複雑に組まれていましたが、ひもとくと次の様な感じのコードでした。
Map sample = new HashMap();
sample.put("idx1", 1);
String ng = (String)sample.get("idx1");
HashMapに、文字列のキーとして、整数の値をバリューとして設定し、HashMapから値を取得する際にはHashMapの値をStringにキャストするコードです。
実行すると赤字の部分で ClassCastExceptionが発生します。
マップに数値(int型)の1を入れてしまって、それがStringだと思い込んでいたためにこんなコードを書いたのだと思います。
実際、マップの他の要素はValueがすべてStringでした。
原因を直接的に対処する方法
直接的な解法は、1を”1″とすることです。相手がオブジェクトなら.toString、数値変数ならString.valueOf(変数)でもいいでしょう。
でも100点ではありません。マップに値をセットするところで問題があります。コード実装中は何時も欠かさずに気にかけていなければ、いずれミスってしまうからです。
Genericsという概念で根本的対応
JDK1.5以降ならGenerics(ジェネリクス)で対応するのが正解でしょう。
以下の様に<String, String>を書いてやることで、このマップはキーも値もStringだよということが明記され、赤字部分はコンパイルエラーになります。
Map<String, String> sample = new HashMap<String, String>();
sample.put("idx1", 1);
String ng = (String)sample.get("idx1");
赤字部分は、最初に書いた直接的に対処する方法で解決できます。
これでうっかりしててもコンパイルが通らなくなるので安心ですね。