以下是我遇到的问题的一个示例:
public interface IFoo { ... }
public abstract class Helper implements IFoo {
public Helper() { ... }
protected abstract X helperMethod();
}
public class Foo extends Helper {
private final String aaa;
@Inject
public Foo(String aaa) { this.aaa = aaa; }
@Override
X helperMethod() { doSomethingUsingWhatsInjected(aaa); }
}
问题在于,当我将IFoo绑定到Foo时:
bind(IFoo.class).to(Foo.class).in(Singleton.class);
似乎helperMethod()
在aaa
被注入之前被调用,因为我看到aaa
为null
。但是,如果我不使用类Helper
并直接在Foo
内嵌其所有代码,guice就不会挣扎。
这两种方法有什么区别?在我们知道helperMethod()
的实施位置之前,为什么要调用IFoo
?我们可以使用Helper
和注射吗?
答案 0 :(得分:2)
您确定没有从helperMethod
的构造函数中调用Helper
吗?您从发布的代码中省略了该部分,但它会与您看到的行为相匹配。
public class Test {
interface IFoo { }
static abstract class Helper implements IFoo {
Helper() { helperMethod(); }
abstract void helperMethod();
}
static class Foo extends Helper {
private final String aaa;
Foo(String aaa) { this.aaa = aaa; }
@Override
void helperMethod() { System.out.println(String.valueOf(aaa)); }
}
public static void main(String[] args) {
// Call helperMethod twice:
// once in the Helper.Helper(), once right here.
new Foo("expected").helperMethod();
// output:
// null
// expected
}
}
Foo做的第一件事就是隐式调用它的超类构造函数,就好像你键入了super()
;这必然发生在子类构造函数中的第一个语句。因此,即使在设置aaa
之类的最终变量之前也会发生这种情况,因此Foo中的重写方法将aaa
视为null。在我的示例中,这不是Guice特有的,但Guice注入可以像其他任何东西一样触发构造函数。
This StackOverflow answer提供了有关此问题的更全面的讨论。