是否有可能在构造函数super()之前进行计算?

假设我有一个类Base,它有一个带有TextBox对象的参数构造函数作为参数。 如果我有一个类简单的以下forms:

public class Simple extends Base { public Simple(){ TextBox t = new TextBox(); super(t); //wouldn't it be nice if I could do things with t down here? } } 

我会得到一个错误告诉我,super的调用必须是构造函数中的第一个调用。 然而,奇怪的是,我可以做到这一点。

 public class Simple extends Base { public Simple(){ super(new TextBox()); } } 

为什么这是允许的,但第一个例子不是? 我可以理解需要首先设置子类,也许不允许在超级构造函数被调用之前实例化对象variables。 但t显然是一个方法(局部)variables,所以为什么不允许呢?

有没有办法来解决这个限制? 有没有一个好的和安全的方法来保存variables的东西,你可能会构造之前调用超级,但后,你已经进入构造函数? 或者,更一般地说,允许在super被实际调用之前完成计算,但是在构造函数中呢?

谢谢。

是的,您的简单案例有一个解决方法。 您可以创build一个私有构造函数,将TextBox作为参数并从您的公共构造函数中调用该构造函数。

 public class Simple extends Base { private Simple(TextBox t) { super(t); // continue doing stuff with t here } public Simple() { this(new TextBox()); } } 

对于更复杂的东西,你需要使用工厂或静态工厂方法。

超级通话之前,我有和计算相同的问题。 有时候你想在调用super()之前检查一些条件。 例如,您有一个创build时使用大量资源的类。 该子类需要一些额外的数据,并可能希望在调用超级构造函数之前先检查它们。 有一个简单的方法解决这个问题。 可能看起来有点奇怪,但是效果很好:

在你的类里面使用一个私有的静态方法来返回超级构造函数的参数,并在里面进行检查:

 public class Simple extends Base { public Simple(){ super(createTextBox()); } private static TextBox createTextBox() { TextBox t = new TextBox(); t.doSomething(); // ... or more return t; } } 

语言要求确保首先可靠地构build超类。 特别是,“如果构造函数没有显式调用超类的构造函数,Java编译器会自动插入对超类的无参构造函数的调用”。

在你的例子中,超类可能依赖于施工时的状态。 你以后可以随时索要一份。

这里有一个广泛的讨论。

第二个例子允许但不是第一个的原因很可能是保持语言整洁,不会引入奇怪的规则。

允许任何代码在超级被调用之前运行将是危险的,因为你可能会混淆本应该被初始化但仍然没有的东西。 基本上,我想你可以在超级本身的调用中做很多事情(例如,调用一个静态方法来计算一些需要去构造函数的东西),但是你永远不能使用任何东西完全构build的对象,这是一件好事。

这就是Java的工作原理:-)为什么select这种方式有技术上的原因。 在调用super之前,你不能对本地进行计算的确很奇怪,但是在Java中,对象必须首先被分配,因此它需要一直到Object,这样所有的字段在被意外的moddify之前被正确的初始化他们。

在你的情况下,大部分时间是一个getter,允许你访问你给super()的参数。 所以你会使用这个:

超级(新的TextBox());
最终的TextBox框= getWidget();
做你的事...