大家都知道java构造 的使用方法吧,
可能大家都用它来进行对象的初始化。
就像下面这样一个例子。
public
class
Test
...
{
public
static
void
main(String [] args)
...
{
Entry e
=
new
Entry();
System.out.println(
"
the val value return ---->
"
+
e.value());
}
}
class
Entry
...
{
public
int
val;
public
Entry()
...
{
val
=
getVal();
//
Entry构造函数
}
public
int
getVal()
...
{
return
6
;
}
public
int
value()
...
{
return
val;
//
返回val值
}
}
运行Test,得到的值应该是什么? 对,就是6.
我们可以稍微加点东西,看看下面这个。
public
class
Test
...
...
{
public
static
void
main(String [] args)
...
...
{
Entry1 e1
=
new
Entry1();
//
Entry改为 Entry1
System.out.println(
"
the val value return ---->
"
+
e1.value());
}
}
class
Entry
...
...
{
public
int
val;
public
Entry()
...
...
{
val
=
getVal();
//
Entry构造函数
}
public
int
getVal()
...
...
{
return
6
;
}
public
int
value()
...
...
{
return
val;
//
返回val值
}
}



//
以下是新添加的代码

class
Entry1
extends
Entry
//
继承自Entry
//
没有覆盖父类的构造函数 和 value函数

...
{
public
int
val
=
16
;
public
int
getVal()
...
{
return
val;
}


}
结果是多少?
应该是16吧?
错了,结果是0.
-------------------------------------------------
怪了,怎么会这样呢?
明明这个函数已经有了实现的代码了呀?
事实是,当Entry1的getVal()函数开始被调用时,他的实例变量val初始化工作还未来得及进行!
这个getVal()函数是在父类Entry的构造函数中被调用的。
而父类的构造函数是被Entry1的构造函数自动调用的。
当运行权进入子类Entry1的getVal()时,它的val变量还来不及初始化,在这样的情况下,
所有的这些实例变量都仅仅只会被设置为缺省的处置。
所以此时val的值为0,被传到了调用的函数中。
于是输出结果为:0.
--------------------------
当我们的java程序构造函数调用非final的函数时,
就有可能发生上面的意外。
当然了,以上的错误不是很常见,不过,理解之后,
一旦遇上,就不会半天找不到解决方案了。
本文通过两个实例探讨了Java构造函数中调用非final方法可能导致的意外结果,特别是当子类覆盖父类变量但未调用super()时,可能会导致变量初始化前就被访问。
2035

被折叠的 条评论
为什么被折叠?



