在构造函数内调用non-final函数时要当心

当程序新建一个class对象时,class构造函数会被调用。构造函数的目的在于将对象初始化。构造函数在运行期间可以调用class的某些函数,这很普遍,因为那些被调用的函数或许包含一些初始化动作。举个例子:

class Base
{
  private int val;
  Base()
  {
    val = lookup();
  }

  public int lookup()
  {
    int num = dbLookup();//假设此时num=5
    return 5;
  }


  public int value()
  {
    return val;
  }
}

        class Base的构造函数调用了一个non-final函数lookup(),查询数据库中的一些数据。这段代码的运转与设想相同,Base的instance数据val被赋值为5.

        想像一下,如果一个derived class覆写了Base的lookup()会怎么样?这种做法可能导致不易察觉的结果。例如:

class Base
{
  private int val;
  Base()
  {
    val = lookup();
  }

  public int lookup()
  {
    int num = dbLookup();
    return 5;
  }

  public int value()
  {
    return val;
  }
}

class Derived extends Base
{
  private int num = 10;
  public int lookup()
  {
    return num;
  }
}


class Test
{
  public static void main(String args[])
  {
    Derived d = new Derived();
    System.out.println("From main() d.value() returns " +
                       d.value());
  }
}

代码输出如下:

From main() d.value() returns 0

        问题出在Derived的lookup()返回值居然是0。你可能奇怪这是怎么发生的,明明已经有了函数实现代码呀!该函数返回instance变量num,它在instance变量初始化时被赋值为10。事实真相是,当Derived的lookup()开始执行时,其instance变量初始化工作还未来得及进行呢。

        注意,这个lookup()是在Derived对象建构期间由Base构造函数调用的,而Base构造函数是被Derived构造函数自动调用的。当执行权进入Deived的lookup()时,其instance变量初始化行为尚未进行。这种情况下,那些instance变量仅仅被设置为缺省初值(default initial values)。因此当时的val被设置为0,于是0被传出去(Praxis32非常细致地分析了对象的建构和初始化步骤)。

        当构造函数调用non-final函数时,就有可能发生这种错误。如果该函数被一个derived class覆写,而且该函数返回一个在“instance变量初始化期间”被初始化的值,就会产生问题。这种错误或许不太常见。不过知道它的存在还是好的,万一哪天遇上了,就可以节省大量时间。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值