2010-04-05 89 views
25

我正嘗試移植一個小項目,用Guice替換一些工廠(這是我第一次Guice試驗)。然而,當我試圖注入泛型時,我被卡住了。我設法提取與兩個階級,一個模塊一個小玩具例子:Guice注入仿製藥

import com.google.inject.Inject; 

public class Console<T> { 
    private final StringOutput<T> out; 
    @Inject 
    public Console(StringOutput<T> out) { 
    this.out = out; 
    } 
    public void print(T t) { 
    System.out.println(out.converter(t)); 
    } 
} 

public class StringOutput<T> { 
    public String converter(T t) { 
    return t.toString(); 
    } 
} 

import com.google.inject.AbstractModule; 
import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.TypeLiteral; 


public class MyModule extends AbstractModule { 

    @Override 
    protected void configure() { 
    bind(StringOutput.class); 
    bind(Console.class); 
    } 

    public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new MyModule()); 
    StringOutput<Integer> out = injector.getInstance(StringOutput.class); 
    System.out.println(out.converter(12)); 
    Console<Double> cons = injector.getInstance(Console.class); 
    cons.print(123.0); 
    } 

} 

當我運行這個例子,我的一切是:

在線程異常「主要」 com.google.inject.CreationException :Guice創建錯誤:

1) playground.StringOutput<T> cannot be used as a key; It is not fully specified. 
    at playground.MyModule.configure(MyModule.java:15) 

1 error 
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354) 
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152) 
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105) 
    at com.google.inject.Guice.createInjector(Guice.java:92) 

我試圖尋找錯誤消息,但沒有找到任何有用的提示。進一步在Guice常見問題解答中,我偶然發現了一個關於如何注射仿製藥的問題。我嘗試添加以下綁定在configure方法:

bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>()); 

但沒有成功(同樣的錯誤消息)。

有人可以解釋我的錯誤信息,並提供一些提示嗎?謝謝。

回答

27

我認爲你看到的具體問題可能是因爲bind(Console.class)聲明。它也應該使用TypeLiteral。或者,你可以只綁定那些和JIT綁定將爲你照顧它,因爲這裏涉及的兩個類型都是具體的類。

另外,你應該檢索Console有:

Console<Double> cons = 
    injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){})); 

編輯:您不必僅僅因爲你使用的是TypeLiteral綁定到一個實例。你可以這樣做:

bind(new TypeLiteral<Console<Double>>(){}); 

當然,就像我說的上面,你可以使用直接跳過,在這種情況下,並檢索從噴射器Console一個Key基礎上,TypeLiteral和結合將是隱含的。

+0

謝謝。我不知道如何將TypeLitteral綁定到控制檯,因爲我無法創建沒有StringOutput實例的控制檯實例。你能詳細說明嗎? – paradigmatic

+0

看我的編輯...你不需要使用toInstance()。 – ColinD

+0

我剛試過。它只適用於我定義類型litterals和y使用密鑰來獲取實例。所以我無法做出明確的約束。 – paradigmatic