オーバーロードメソッドを、型推論でコールしようとしても
型情報は消えているから、注意が必要だぞ!
自分はちょっと勘違いしていたので、共有しておきます。
テストしてみる
オーバーロードされている関数を用意
まず、テスト用のオーバロードされている関数を用意。
Object型と、Integer型を受け取る関数ですね。
private static void test(Object obj)
{
System.out.println("DUMP Object:" + obj);
}
private static void test(Integer value)
{
System.out.println("DUMP Integer:" + value);
}
test関数をwrapするような関数があったとして
で、ジェネリクスを利用して、ラップするようなメソッドが欲しいなぁと思って
下記のような関数を用意しました。
private static <T> void testWrap(Supplier<T> supplier)
{
test(supplier.get());
}
型情報は消えてるよ
Integer型の関数をコールしてほしいのですが、型情報が消えているため、
Object型を受け取る関数がコールされます。
public static void main(String[] args)
{
Integer a = 1;
testWrap(() -> a); // test(Integer) じゃなく、test(Object) がコールされる。
}
型情報が消えるとは
上記の testWrap関数は、
コンパイルされるとTがObjectに置き換わった状態になります。
private static <T> void testWrap(Supplier<T> supplier)
{
test(supplier.get());
}
private static void testWrap(Supplier<Object> supplier)
{
test((Object)supplier.get());
}
コンパイル後のクラスファイルはこんな感じになっている。
これが型情報が消えるという事。
なので、いくら型パラメータを渡したとしても、
コンパイルしたクラスファイルでコールしているのは、test(Object) なのです。