我有一个类和一个工厂函数,它创建了扩展该类的新匿名类对象。但是,匿名类对象都有一个方法,其中有对其他对象的引用。在我的完整程序中,我需要这个来创建和组合解析器,但我在这里删除了代码。
class Base{
public Base run(){
return null;
}
static Base factory(final Base n){
return new Base(){
public Base run(){
return n;
}
};
}
}
public class CircularReferences{
public static void main(String args[]){
final Base a, b;
a = Base.factory(b);
b = Base.factory(a);
}
}
我得到CircularReferences.java:17; error: variable b might not have been initialized
。这是真的,它不是,但是我不能为这些变量留出空间然后使用对这些空间的引用来初始化它们,这些空间在实际使用之前将填充适当的值?我可以单独使用new
构造函数吗?如何创建这些变量以便它们相互引用?
答案 0 :(得分:1)
快速回答是你无法做到这一点。如果你绝对必须做这样的事情,那么在类上使用私有的setter并在构造它们之后将它们绑定在一起(即使用强制不变性而不是最终字段)。希望很明显我认为这不是一个好主意 - 我只是想在回答我真正想要的方式之前回答你的实际问题。
好的 - 现在已经不在了,这里是真正的响应:
一般来说,这种情况是一个强有力的指标,需要重构来分离问题。换句话说,Base类可能试图负责太多事情。
我意识到这个例子是设计的,但是考虑一下什么功能需要循环依赖,然后将 功能分解成一个单独的类/对象,然后传递给两个Base构造函数。
在复杂的体系结构中,循环依赖链可能会变得非常大,但严格强制最终字段是寻找这些类型的重构机会的好方法。
如果您有一个具体的例子,我很乐意帮助您提供一些重构建议来打破这样的依赖。
提供了具体的例子 - 这是我的建议:
似乎有人担心基于令牌获得适当的ParseStrategy。 ParseStrategyProvider。因此会有一个TopLevelParseStrategy读取下一个标记,查找适当的解析策略并执行它。
TopLevelParseStrategy将保存对ParseStrategyProvider的最终引用。
ParseStrategyProvider需要有一个注册方法(即registerStrategy(token,parseStrategy))。
这与通过私有设置器实现强制不变性这一功能没有多大区别(registerStrategy方法与私有设置器的所有意图和目的相同),但设计更具可扩展性。
所以你有:
public ParseStrategy createParser(){
ParseStrategyProvider provider = ParseStrategyProvider.create();
TopLevelParseStrategy topLevel = new TopLevelParseStrategy(provider);
provider.registerStrategy("(", topLevel);
// create and register all of your other parse strategies
return topLevel;
}