Zak*_*aki 3 java instance-variables instance
下面是一些示例代码,
class Base
{
private int val;
Base() {
val = lookup();
}
public int lookup() {
//Perform some lookup
// int num = someLookup();
return 5;
}
public int value() {
return val;
}
}
class Derived extends Base
{
private int num = 10;
public int lookup() {
return num;
}
}
Run Code Online (Sandbox Code Playgroud)
class Test
{
public static void main(String args[]) {
Derived d = new Derived();
System.out.println("d.value() returns " + d.value());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:d.value()返回0 //我期望10,因为lookup()被覆盖,但不是0!谁有人澄清这个?
Derived在其查找方法执行时,实例变量的初始化没有发生.如何Derived在调用其方法时确保初始化实例变量?
好吧,首先,由于缺少someLookup方法,该代码无法编译.
无论如何,除此之外,我认为您的问题是由于构造函数的分层运行方式,您的预期无效.
超类'构造函数总是在子类'之前运行,这包括子类'变量的初始化器(它们实际上作为构造函数的一部分运行).因此,当您创建实例时Derived,会发生以下情况:
Base构造函数首先被调用.lookup()被调用,它使用实现Derived.num返回,这是此时的默认值,因为尚未运行Derived的构造函数和初始值设定项.val 设置为0.Derived初始化和构造都运行-呼吁lookup从这个点上会返回10.一般来说,出于这个原因从构造函数中调用非final方法是个坏主意,许多静态分析工具会警告你不要这样做.它类似于在构造过程中让对象引用泄漏,你可以得到一个使类级别不变量无效的实例(在你的情况下,Derived的num"总是"10但在某些点它可以看作是0).
编辑:请注意,对于这种特殊情况,没有任何其他代码,您可以通过创建num一个常量来解决问题:
class Derived extends Base
{
private static final int num = 10;
...
Run Code Online (Sandbox Code Playgroud)
这实际上会做你想要的,因为静态初始化程序是在加载类时运行的(必须在调用构造函数之前发生).然而,这确实假设它适用于:
a)类的所有实例共享同一个num变量; b)num永远不需要改变(如果这是真的那么(a)是自动的).
在您给出的确切代码中显然就是这种情况,但我希望您可能会省略额外的功能以简化.
我在这里包含这个用于比较和兴趣,而不是因为它是一般意义上的这个"问题"的解决方法(因为它不是).
| 归档时间: |
|
| 查看次数: |
1893 次 |
| 最近记录: |