【问题标题】:Google Guice + generics: Is there some magic behind the curtains?Google Guice + generics:幕后有什么魔力吗?
【发布时间】:2015-05-25 04:51:51
【问题描述】:

在我看来,Guice 实现在处理泛型时做了一些非常棘手的事情。看起来它在运行时知道在编译时使用的泛型类型。我们来看一个简单的例子:

@Inject
public void Bar(Provider<Foo> genericInjector){
...

在运行时,Guice 将在此处注入 Provider 的正确实现(即提供 Foo 实例的那个)。但据我所知,泛型类型在运行时被擦除(参见:Type Erasure)。所以 Guice 在运行时真正看到的是:

@Inject
public void Bar(Provider genericInjector){
....

那么,Guice 怎么可能知道要注入 Provider 的哪个实现呢?

【问题讨论】:

    标签: java generics guice


    【解决方案1】:

    不,类型擦除不会擦除所有内容。您仍然可以获取字段类型、参数等。Provider&lt;Foo&gt; 信息 仍然存在于执行时。例如,请参阅Method.getGenericParameterTypes

    没有保留的是关于特定对象的类型信息。例如,如果我写:

    List<String> list = new ArrayList<String>();
    showType(list);
    
    ...
    
    
    public static void showType(List<?> list)
    {
        // ???
    }
    

    无法确定它是ArrayList&lt;String&gt;,因为该对象不再具有该信息。

    请参阅Java Generics FAQ 了解更多信息。很多

    【讨论】:

    • 好的!我相信这正是 Inerdial 的意思,但你的回答对我来说更清楚。我会检查一下,如果你是对的,我会给你正确的答案:)。
    【解决方案2】:

    一种常见的误解是,类型擦除的工作方式是编译器实质上会删除尖括号及其内部的内容,然后就好像源代码是 Java 1.4 一样。事实并非如此。

    通用参数不会从方法签名中删除——方法签名是“编译时”的。 “运行时”构造中不存在通用参数——你无法判断给定对象是用什么类型参数实例化的。

    【讨论】:

    • 感谢您的回答,但我还是不明白。你说的是什么意思:“方法签名是编译时间”?是不是泛型参数在运行时没有从方法签名中删除,而是从其他任何地方删除?我从来没有听说过这样的区别:(。
    • @PiotrSobczyk:Angelika Langer's FAQ on type erasure 可能会比我希望的更好地解释这一点。
    • 非常感谢,这实际上是非常有用的链接,更新后的答案更加清晰。不幸的是,我只能给你一个赞成票:(。乔恩更精确一点。
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 2012-11-30
    • 2011-04-02
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 2023-03-29
    • 2016-09-23
    相关资源
    最近更新 更多