Java对象实例是何时被创建


  对象实例何时被 缔造,这个问题 兴许你用一句话就能 答复完了 。然而它的潜在陷阱却 一般被人 忽视,这个问题 兴许并不像你想的那么 容易,不信请你耐心看下去 。

我前几天问一个同学,是否在调用 构造函数后,对象才被实例化?他不假 考虑的 答复说是 。

请看下面代码:

Java代码

Date date=new Date();

em.out.println(date.getTime());

新手在刚接触 构造函数这个概念的时候 。他们 一般得出这样的 论断:对象实例是在调用 构造函数后 缔造的 。由于调用 构造函数后,调用 引用(date)的实例 步骤便不会报NullPointerException的 舛误了 。

二、 教训者的观点

然而,稍稍有 教训的Java程序员便会发现上面的解释并不正确 。这点从 构造函数中我们 可以调用this 要害字 可以看出 。

请看下面代码:

Java代码

public class Test

{

public Test()

{

this.DoSomething();

}

private void DoSomething()

{

System.out.println("do init");

}

}

这段代码中我们在 构造函数中已经 可以操作对象实例 。这也就 证实了 构造函数其实只不过用于初始化,早在进入 构造函数之前 。对象实例便已经被 缔造了 。

三、父类 构造函数

当 缔造一个有父类的子类的时候 。对象的实例又是何时被 缔造的呢?我们 兴许接触过下面经典的代码:

Java代码

public class BaseClass

{

public BaseClass()

{

System.out.println("create base");

}

}

public class SubClass

{

public SubClass()

{

System.out.println("create sub");

}

public static void main(String[] args)

{

new SubClass();

}

}

   后果是先输出create base,后输出create sub 。这个 后果看起来和 事实世界 彻底 统一,先有老爸,再有儿子 。 因此我相信有众多程序员跟我一样会认为new SubClass()的过程是:实例化BaseClass->调用BaseClass 构造函数初始化->实例化SubClass->调用SubClass 构造函数初始化 。然而十分 可怜的是,这是个 舛误的观点 。

  四、奇怪的代码
以下代码是为了 反驳上面提到的 舛误观点 。然而这种代码其 着实工作中甚少浮现 。

Java代码

public class BaseClass

{

public BaseClass()

{

System.out.println("create base");

init();

}

protected void init()

{

System.out.println("do init");

}

}

//

public class SubClass

{

public SubClass()

{

System.out.println("create sub");

}

@Override

protected void init()

{

assert this!=null;

System.out.println("now the working class is:"+this.getClass().getSimpleName());

System.out.println("in SubClass");

}

public static void main(String[] args)

{

new SubClass();

}

}

这段代码运行的 后果是先调用父类的 构造函数,再调用子类的init() 步骤,再调用子类的 构造函数 。

这是一段奇异的代码,子类的 构造函数竟然不是子类第一个被执行的 步骤 。我们早已习惯于通过super容易的调用父类的 步骤,然而 如同从没这样尝试从父类调用子类的 步骤 。

再次申明,这只不过个示例 。是为了与您一同探讨对象实例化的 机密 。通过这个示例,我们再次印证了开头的观点:早在 构造函数被调用之前,实例便已被制造 。若该对象有父类,则早在父类的 构造函数被调用之前,实例也已被制造 。这让java显得有些不面向对象,原来老子儿子其实是一块儿 诞生的 。

  五、奇怪但惊险的代码

本篇是对上篇奇怪代码的连续 。然而这段代码更加 存在 不解性, 了解不当将会让你浮现致命失误 。

请看下面代码:

Java代码

public class BaseClass {

public BaseClass()

{

System.out.println("create base");

init();

}

protected void init() {

System.out.println("in base init");

}

}

public class SubClass extends BaseClass{

int i=1024;

String s="13 leaf";

public SubClass()

{

System.out.println("create sub");

init();

}

@Override

protected void init() {

assert this!=null;

System.out.println("now the working class is:"+this.getClass().getSimpleName());

System.out.println("in SubClass");

/////////////great line/////////////////

System.out.println(i);

System.out.println(s);

}

public static void main(String[] args) {

new SubClass();

//oh!my god!!

}

}