在我看来,Guice实现在处理泛型时做了一些非常棘手的事情。看起来它在运行时知道关于在编译时使用的泛型类型。让我们看一个简单的例子:
@Inject
public void Bar(Provider<Foo> genericInjector){
...
在运行时,Guice将在此处注入Provider
的正确实现(即提供Foo
个实例的实现)。但据我所知,泛型类型在运行时被擦除(参见:Type Erasure)。所以Guice在运行时真正看到的就是:
@Inject
public void Bar(Provider genericInjector){
....
那么Guice怎么可能知道要注入哪个Provider
实现呢?
答案 0 :(得分:10)
不,类型擦除不会删除所有内容。您仍然可以获取字段类型,参数等。Provider<Foo>
信息 在执行时仍然存在。例如,请参阅Method.getGenericParameterTypes
。
不保留的是有关特定对象的类型信息。例如,如果我写:
List<String> list = new ArrayList<String>();
showType(list);
...
public static void showType(List<?> list)
{
// ???
}
由于该对象不再具有该信息,因此无法确定它是ArrayList<String>
。
有关 lot 的更多信息,请参阅Java Generics FAQ。
答案 1 :(得分:2)
一种常见的误解是,类型擦除的工作方式是编译器基本上删除了尖括号及其内部的内容,然后就像源是Java 1.4一样。事实并非如此。
通用参数不会从方法签名中删除 - 方法签名是“编译时”。 “运行时”构造中不存在通用参数 - 您无法分辨给定对象实例化的类型参数。