public MyClass(Processor<String> strProcessor, Processor<Integer> intProcessor)P
{
//Simple enough, but alot of boiler plate is required to launch this constructor.
}
//and to invoke
new MyClass(PRocessorFactory.get(....), ProcessorFactory.get(...));
@Inject
public MyClass(Processor<String> implStr, Processor<Integer> implInt)
{
//Now , this method will work magically, because Guice is capable of
//Using the loaded modules, which define bindings between generics and their implementations
}
//Elsewhere I simply define a single guice module that does the binding, and make sure to load it before my application launches.
# 1 楼答案
Guice中^{} 的目的是允许您将类和实例绑定到泛型类型(指定类型参数),从而避免泛型在Java中没有具体化这一事实所导致的问题,也就是说,擦除在运行时隐藏了
SomeInterface<String>
和SomeInterface<Integer>
之间的差异TypeLiteral
通过创建泛型类型的特殊子类,允许泛型参数的值在擦除后仍然有效TypeLiteral
的用法示例:这将
SomeInterface<String>
类型的参数绑定到SomeImplementation
类有关一些背景信息,请查看超级类型标记上的this blog post和类型文字上的then this one
# 2 楼答案
对于泛型类型不能有类文本这一事实,} (这是来自Google Guice,但同名的Java EE类具有完全相同的用途)给出了一个如何使用它的示例:
TypeLiteral
类是一种变通方法。API doc of ^{这指定任何类型为
PaymentService<CreditCard>
的自动注入引用都将由具体类CreditCardPaymentService
实现,而PaymentService<Coupon>
的选项将由不同的类实现。没有TypeLiteral
,这是不可能的,因为Java编译器将只接受PaymentService<CreditCard>.class
,只接受PaymentService.class
请注意,这还需要使用匿名子类(在
new TypeLiteral<PaymentService<CreditCard>>()
之后的{}
),以解决类型擦除问题# 3 楼答案
与Guice中的任何东西一样,模块化、可重用性和样板文件的删除是所有实用程序的核心概念
当然,您在Guice中所做的任何事情都可以在Java中模仿——代价是大量的样板文件,所以。。。真正的问题是:
我们如何使用typeliteral来编写更多模块化/可重用组件
Guice中TypeLiterals的强大之处在于,它允许您引用服务的实现,而无需定义该服务是什么
让我们从一个程序中的一个简单列表开始,在这个程序中,我们有许多不同处理的列表类型:
现在,我应该如何处理这些字符串?在运行时,没有办法“知道”它是一个字符串列表。所以,很多时候我可能会创建一个工厂,像这样,为我获取处理对象:
因此,我可能会使用工厂(带有一系列if/else或case语句)为不同的数据类型定义处理器。对于使用这些处理器并需要访问各种处理器实现的对象,我的构造函数可能如下所示:
到目前为止一切都很好。。。直到我们意识到有更好的方法:
在Guice世界中,我可以忘记编写这个工厂——相反,我可以显式地将类绑定到处理器。这样做的好处是没有静态依赖关系——需要使用处理器实现的类不需要对工厂有任何静态依赖关系——而是直接注入类。因此,我可以轻松定义一个使用复杂依赖项的类,而无需构建工厂感知的类生成器。。。因此,我的样板要少得多:
这里有一个很好的教程,介绍了接口实现和绑定示例:http://thejavablog.wordpress.com/2008/11/17/how-to-inject-a-generic-interface-using-guice/
# 4 楼答案
这是人们在java中绕过泛型擦除的一种方式。当您想要将一些实现绑定到参数化(通用)接口时,您需要它。在Guice文档中找到一些用法:
这个公认的奇怪构造是绑定参数化类型的方法。它告诉Guice如何满足PaymentService类型元素的注入请求。CreditCardPaymentService类必须实现PaymentService接口。Guice当前无法绑定或注入泛型类型,例如Set;必须完全指定所有类型参数
# 5 楼答案
我将简化TypeLiteral存在的答案/原因<>;在GUICE:
如果java允许您编写:
bind(FooInterface<String>.class).to(FooImplementation.class);
这样就完成了,不需要使用TypeLiteral<>
但是java对泛型有这种“类型擦除”的功能,所以
FooInterface<String>.class
甚至不会被编译所以你使用:
bind(new TypeLiteral<FooInterface<String>>() {}).to(FooImplementation.class);
“new TypeLiteral<;Interface>;(){}”将创建一些匿名类,并从中创建一个新对象。您可以想象,该对象知道关于接口的tpye信息的所有信息,因此GUICE使用该对象来执行DI魔术