各位仁兄,前几日我在项目中写了类似这么一段代码
AbstractClass
package com.my.study;
public abstract class AbstractClass {
private final Object comm;
protected AbstractClass(Object comm) {
super();
this.comm = comm;
this.buidSelf();
this.buildChildren();
}
public Object comm(){
return this.comm;
}
protected abstract void buidSelf();
protected abstract void buildChildren();
}
TestClass
package com.my.study;
public class TestClass extends AbstractClass {
public TestClass(Object o) {
super(o);
}
@Override
protected void buidSelf() {
System.out.println("buildSelf");
}
@Override
protected void buildChildren() {
System.out.println("buildChildren");
}
public static void main(String g[]) {
new TestClass(new Object());
}
}
看看这代码 有什么问题呢?不管三七二十一,先跑跑看,结果如图
一切ok,没问题
但究竟有什么问题呢?请看以下代码
package com.my.study;
public class TestClass extends AbstractClass {
private Object a=null;
public TestClass(Object o) {
super(o);
}
public void run(){
System.out.println(a.toString());
}
@Override
protected void buidSelf() {
System.out.println("buildSelf");
}
@Override
protected void buildChildren() {
System.out.println("buildChildren");
a=new Object();
}
public static void main(String g[]) {
new TestClass(new Object()).run();
}
}
再运行一下,结果如下图
怎么回事,为啥会有exception?不是给它赋值了吗?Why?
可以明确的告诉你,如果在定义a的时候没有给赋值null,这个异常是不会出现滴。
这...java 究竟是如何加载对象的?
就拿此例说明吧,在java new 一个对象的时候,首先声明了自己的所有成员变量,所有成员变量都是null,然后去构造父类,在构造父类的时候我们这里调用了子类的钩子方法,给a赋值为 new object(),父类构造完成之后回到子类构造函数,执行子类构造的内容,此时会检查你在声明成员变量时候有没有给它初始值,有的话就会去执行赋值语句,有异常的代码相当于在声明与赋值之间执行了父类的构造函数。最终a变成了null。
经此解释你是否明白为啥了么?呵呵,不明白就自己去debug一下 就海阔天空了:)
由此忠告自己以及各位看客:务必不要在构造函数中调用多态。如果你非要这么写那就请不要在调用的方法中使用子类的成员变量