我在 IB 的 API 中声明实例变量时见过this
使用,但这似乎是个坏主意。分配是否保证在this
完全构建后发生?有关系吗?
我认为实例变量是在构造函数之前初始化的,因为它们可以被构造函数使用。this
如果使用有一些例外吗?
如果它以某种方式起作用,这似乎不是一个好主意 -second
可用于FirstClass
的构造函数?如果是,是在 ?SecondClass
之前构建的FirstClass
?这意味着num
最终是 3 并且i
是 10?还是会出现运行时错误?无论哪种方式都有任何保证吗?
public class FirstClass {
SecondClass second = new SecondClass(this);
public int i = 3;
FirstClass(){
i = second.DoSomething();
}
}
public class SecondClass{
private int num = 10;
SecondClass(FirstClass first){
num = first.i;
}
public int DoSomething(){
return num;
}
...
}
我想 IB 拥有一支相当稳固的开发人员团队,并且知道他们在做什么。你怎么看:
- 可以
this
用来初始化实例变量吗? - 应该这样做吗?
编辑
答案是肯定的,有保证的结果(现在 - 但请继续阅读......),但不应该这样做,因为它很容易在不经意间对可能改变这个“保证”结果的代码进行更改。
我现在知道在构造新对象(例如FirstClass
JVM)时:
- 为此类及其所有超类的所有实例变量分配内存。
- 用默认值初始化所有变量
- “正确”按文本顺序初始化所有变量,从其最高超类(即对象)开始并以此类结束 - 因此
second
在 i 初始化为 3 之前被初始化(即构造)。 - 如果这些“正确”初始化中的任何一个调用另一个方法或另一个构造函数,这将在调用第一个构造函数之前完成- 因此
second
在构造函数运行之前构造并返回FirstClass
。 - 如果实例初始化调用了另一个构造函数(例如在第 4 项中),它会经历与第 1 项相同的过程(内存分配、初始化等)
这样做不好的原因是“保证”结果可以通过两种方式改变:
- 如果源代码顺序改变(例如,如果在构造
i
之前被初始化second
),结果将会改变。很容易不注意到这一点。 - 如果有人将我们的类(或多个类)子类化,他们可能不会意识到微妙的平衡,并且可能会在覆盖时改变一些影响结果的东西。
所以看起来 IB 的 API 受到了这种微妙的影响,我现在必须牢记这一点。
感谢 Emil H 的回答和他对这篇文章的指导,这最终让我理解了上面的内容:http ://www.artima.com/designtechniques/initializationP.html - 强烈推荐阅读。
还要感谢 Alexander Drobyshevsky 在他的回答中提出了非常相似的观点。