型パラメータのある場合
型パラメータのあるインターフェースについてどのようにバインディング指定し、どのようにインスタンスを取得するか?
型パラメータを指定しない方法
型パラメータを無視してバインディング指定を行い、インスタンス注入を行う。
package test; import com.google.inject.*; public class TypeParameterZero { public interface Test<T> {} public static class TestA implements Test<String> {} public static class Sample { @Inject Test one; // 型パラメータ無視 void show() { System.out.println(one); } } public static void main(String[]args) { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Test.class).to(TestA.class); // 型パラメータ無視 } }); Sample sample = injector.getInstance(Sample.class); sample.show(); } }
結果は以下になる。
test.TypeParameterZero$TestA@64dc11
もし、注入される側を以下のようにすると、
@Inject Test<String> one;
以下のエラーとなる。Guice側はバインディング時と注入時の型パラメータを把握しているのである。
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors: 1) No implementation for test.TypeParameterZero.test.TypeParameterZero$Test<java.lang.String> was bound.
この場合、バインディング指定を以下のようにすればよい。
bind(new TypeLiteral<Test<String>>() {}).to(TestA.class);
もちろん以下のようには記述できない。TypeLiteralはこのような場合の代替として使う。
bind(Test<String>.class).to(TestA.class);
逆に、バインディング時には上記のようにTypeLiteralを用いて型パラメータを指定し、注入側に生の型を使うと、
@Inject Test one;
やはりエラーとなる。
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors: 1) No implementation for test.TypeParameterZero$Test was bound.