2012-11-08 95 views
12

我們試圖用Guice重構一個項目。這個想法是將界面的所有界面綁定到像法國波蘭這樣的混凝土物體。Guice注入空指針

我們有一個模塊綁定:

public class StandardModule extends AbstractModule { 

    @Override 
    protected void configure() { 

     bind(Language.class).to(Polish.class); 

    } 
} 

而一個CLASSE(AboutDialog.java)使用該注射對象:

@Inject Language language; 

public AboutDialog(JFrame parent) { 
    super(parent, "", true); 
    this.language=language; 
    this.setTitle(language.getLanguageInUse().getString("AboutDialog.title")); 
    this.parent = parent; 
    try { 
     jbInit(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    pack(); 
} 

我們有作爲的結果:

java.lang.NullPointerException at net.sf.jmoney.gui.AboutDialog.<init>(AboutDialog.java:67) 

67行是:

this.setTitle(language.getLanguageInUse().getString("AboutDialog.title")); 

我們的界面是:

public interface Language { 

    public ResourceBundle getLanguageInUse(); 
} 

和波蘭類:

public class Polish implements Language { 

    private ResourceBundle languageInUse; 

    public Polish() { 
     languageInUse = ResourceBundle.getBundle(Constants.LANGUAGE_PL); 
    } 

    public ResourceBundle getLanguageInUse() { 
     return languageInUse; 
    } 


} 

我們輸了...

+0

你應該改變你的代碼一點點,看看那裏的NPE被拋出 '代碼 資源包捆= language.getLanguageInUse(); 字符串標籤= bundle.getString(「AboutDialog.title」); ' –

+0

空對象是語言。我們認爲注射不起作用。 – user1810567

+0

你如何創建AboutDialog?我不認爲你正在與Guice創建對話框,因爲Guice需要一個空構造函數,或者你需要將jframe綁定到某個地方? –

回答

8

我假設你不與幫助創建AboutDialog的Guice。

你可以做的是使用injector.injectMembers(this)其中thisAboutDialog

最好的方法是將由Guice創建AboutDialog,因此所有成員都將被注入。

7

您正在使用「現場注入」。這將使它很難在構造函數中使用注入的值;即使Guice要創建對象(現在不會發生),或者您要使用injector.injectMembers(aboutDialog),構造函數將在注入器有機會注入所需字段之前運行。

創建一個需要變量參數以及注入參數的類會有點棘手。這給你留下了幾個選擇:

  • 注入JFrame。如果您知道創建構造函數時要使用哪個JFrame,那麼只需在模塊中使用bind(JFrame.class).toInstance(myJFrame);即可。然後Guice可以完全創建AboutDialog。

  • 手動創建工廠。這樣,您可以注入AboutDialog.Factory,只需撥打create即可獲得您的AboutDialog。它會是這個樣子:

    public class AboutDialog extends JDialog { 
    
        /** Injectable factory. */ 
        public static class Factory { 
        @Inject private Language language; 
    
        public AboutDialog create(JFrame parent) { 
         return new AboutDialog(parent, language); 
        } 
        } 
    
        // no @Inject parameter; you're calling "new" yourself above! 
        public AboutDialog(JFrame parent, Language language) { 
        super(parent, "", true); 
        this.language = language; 
        // ... other initialization 
        } 
    } 
    
  • 通過assisted injection爲你創建一個工廠,讓吉斯線起來。

    public class AboutDialog extends JDialog { 
    
        public interface Factory { 
        public AboutDialog create(JFrame parent); 
        } 
    
        // you need the @Inject, and also the @Assisted to tell Guice to 
        // use the parameter instead of Guice bindings 
        @Inject 
        public AboutDialog(@Assisted JFrame parent, Language language) { 
        super(parent, "", true); 
        this.language = language; 
        // ... other initialization 
        } 
    } 
    
    public class StandardModule extends AbstractModule { 
        @Override protected void configure() { 
        bind(Language.class).to(Polish.class); 
    
        // here every method in AboutDialog.Factory will be implemented 
        // to create the method's return type [AboutDialog] based on 
        // the parameters (like JFrame) and the bindings (like Language) 
        install(new FactoryModuleBuilder().build(AboutDialog.Factory.class)); 
        } 
    } 
    

如問題的意見指出,要確保你得到你的AboutDialog(或通過@Inject ED構造函數/場或從Injector本身,否則AboutDialog.Factory吉斯不知道要注入參數

+0

10我們已成功注入對象和項目完美運作。感謝您的幫助^^。 – user1810567

+0

不客氣!如果問題解決了,請記住[接受答案](http://stackoverflow.com/faq#howtoask)。祝你的項目好運! –

+1

這句話「構造函數將在注入器有機會注入你想要的字段之前運行」這一句節省了我的一天,因爲我不理解爲什麼我的默認構造器中使用的注入字段是空的。謝謝!!! – mljrg