Java では他言語にもあるようにジェネリッククラス(総称型)を定義することができます。ここでは入門編として、ジェネリッククラスを活用し、実行時に発見されるバグをコンパイルの段階で発見できるようにしたサンプルコードを掲載しています。
スポンサーリンク
実行時に例外発生
以下のサンプルコードは、実行時に例外が発生します。文字列をキャストできない数値型にキャストしています。
Exception in thread “main” java.lang.ClassCastException: java.lang.String canno be cast to java.lang.Integer
at TestClass.main(TestClass.java:10)
class ObjectClass { private Object _obj; /* セッター */ public void setObject(Object obj) { this._obj = obj; } /* ゲッター */ public Object getObject() { return this._obj; } } // テストコード public class TestClass { public static void main(String[] args) { String str = "文字列"; ObjectClass strObj = new ObjectClass(); strObj.setObject(str); // 型が違うので例外発生(StringをintにキャストNG) int num = (int)strObj.getObject(); } }
ジェネリッククラスを活用してコンパイル時にエラーを検出
上記のサンプルコードをジェネリッククラスを使って書き換えたモノが以下のコードになります。実行時ではなく、コンパイルの時点でバグを発見できるるようになっています。これは、ジェネリッククラスを使用する利点の一つでもあります。
/* ジェネリッククラスで書き換える */ class ObjectClass<T> { private T _obj; /* セッター */ public void setObject(T obj) { this._obj = obj; } /* ゲッター */ public T getObject() { return this._obj; } } // テストコード public class TestClass { public static void main(String[] args) { String str = "文字列"; // 総称型で定義したクラスに型を割り当てる ObjectClass<String> strObj = new ObjectClass<String>(); strObj.setObject(str); // 以下のように関数に型を指定することもできる //strObj.<String>setObject(str); String str2 = strObj.getObject(); // コンパイルOK // 型が違うのでコンパイルエラー発生 int num = strObj.getObject(); // コンパイルNG //int num = (int)strObj.getObject(); // コンパイルNG } }
コンパイル結果
コンパイルでは以下のようにエラーが検出されます。実行前にバグが発見できることは嬉しいことです。バグに気づくのが早ければ早いほどその後の被害が少ないです。
TestClass.java:14: エラー: 変換できない型 int num = strObj.getObject(); ^ 期待値: int 検出値: String エラー1個