Google guice使用new TypeLiteral<C<T>>() {}
来克服我们无法使用C<T>.class
这一事实。
现在通常如下:
bind(new TypeLiteral<C<T>>() {}).to(MyCSubclassTypedToT.class);
想象一下不同的场景。我们有一个通用接口,我们想要注入,我们的实现由泛型类提供。
Guice允许你这样做:
bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});
另一种方法是扩展MyGenericClass,如下所示:
MyTypedClass extends MyGenericClass<T>
然后像这样绑定它:
bind(MyGenericInterface<T>>() {}).to(MyTypedClass.class);
如果MyGenericInterface被注入了很多(尽管有不同的类型),每次我注入它都使用MyGenericClass,后一种方法导致过于冗长的代码。因此,我倾向于使用前者。
我非常希望听到其他人关于在guice绑定的to子句中使用TypeLiteral的意见。我担心我可能会选择做空,因此不会看到这种方法的缺陷。
答案 0 :(得分:2)
在这种情况下,使用TypeLiteral
进行通用实现会让我觉得好多了。
让我这样说:“如果你没有使用Guice,子类MyTypedClass
会不会存在?” Guice的基本准则是:您不必更改实现类以适应DI框架(除了@Inject
注释之外)。
你从子类化具体而又通用的类中获得了什么?一个很大的损失是你必须在所有子类中复制MyGenericClass的构造函数。总而言之,它似乎是额外的代码而没有太大的收获。
总而言之,使用TypeLiteral
通常没有任何问题。如果它在绑定子句的.to(...)
部分(而不是bind(...)
),它甚至不会影响Module
绑定的公开可见部分,所以我不喜欢我认为有很多事要担心。
答案 1 :(得分:1)
通常有两种情况:
MyGenericInterface
的所有实现绑定到MyGenericClass
MyGenericInterface
的实现
醇>
对于第一种情况,bind(MyGenericInterface).to(MyGenericClass);
就足够了,更简单易懂。
对于第二个场景,您需要将特定类的实现绑定到特定的实现,TypeLiteral将发挥作用。
此外,您的问题中的代码不清楚T
是实际类还是泛型类型。如果是通用类型,
bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});
和
MyTypedClass extends MyGenericClass<T>
不会编译,因为没有提供某些实际的类。