如下代码所示:public class Parent { protected String pStr; public Parent() {
invoke();
} public void invoke() {
System.out.println("Parent invoke " + pStr);
pStr = "Parent pStr";
}
}public class Child extends Parent { private String cStr; public Child() {
super();
} public void invoke() {
System.out.println("Child invoke " + cStr + "; " + pStr);
cStr = "child cStr";
} public static void main(String[] args) {
Child c = new Child();
c.invoke();
}
}
打印出来的结果是:
Child invoke null; null
Child invoke child cStr; null我想问的是:Child c = new Child()这一步 会调用父类构造函数,有一个打印。然后调用子类的构造函数。就是这里吧,子类构造函数是super(),也就是说调用了父类的构造函数对吧,那么为何不再打印一次呢。也就是说最终打印结果我想的是有三行打印。好像哪里理解错了,求指正吧,别的没问题。
invoke();
} public void invoke() {
System.out.println("Parent invoke " + pStr);
pStr = "Parent pStr";
}
}public class Child extends Parent { private String cStr; public Child() {
super();
} public void invoke() {
System.out.println("Child invoke " + cStr + "; " + pStr);
cStr = "child cStr";
} public static void main(String[] args) {
Child c = new Child();
c.invoke();
}
}
打印出来的结果是:
Child invoke null; null
Child invoke child cStr; null我想问的是:Child c = new Child()这一步 会调用父类构造函数,有一个打印。然后调用子类的构造函数。就是这里吧,子类构造函数是super(),也就是说调用了父类的构造函数对吧,那么为何不再打印一次呢。也就是说最终打印结果我想的是有三行打印。好像哪里理解错了,求指正吧,别的没问题。
"Child c = new Child()这一步 会调用父类构造函数,有一个打印。" 这个调用就是通过子类的super()调用的。
"然后调用子类的构造函数。" 这句应该是理解为,执行子类的构造方法的剩余语句。(楼主的代码里构造方法里没有其他语句了。初始化就算结束了。
推荐楼主参考一下:
http://wenwen.soso.com/z/q191435823.htm
super();
}这个是调用父类的构造方法,楼主应该是知道的,而父类的构造方法 public Parent() { invoke(); } 调用了invoke();这个方法,然而楼主肯定以为invoke()这个方法就是父类里面的那个,其实是错的,invoke()这个方法应该是子类Child里面的那一个。然而为什么输出又会是NULL呢?这个是因为父类里面
没有cStr这个变量。总结一下:用super()调用父类构造方法,其实就是调用父类中有的同时又存在于子类的方法和变量。就是取交集啦~~~~~~不知道楼主能不能完全理解,要是不能理解的话再留言吧。
所以在构造方法里安全的方案是调用私有方法。
一次是子类构造调用父类构造,父类构造调用父类invoke方法
一次是子类对象对用自己的invoke方法
其实是子类的invoke()调用了两遍,第一遍没有初始化都,第二遍时cStr已经初始化了。
为啥第一遍调用的子类的invoke是因为引用类型是子类Child c = new Child();
多态当然调用自己运行时类型的方法了。
2、子类构造函数中调用父类构造函数,父类构造函数中的invoke调的是子类重写的invoke
3、相当于子类invoke调了两遍,第一遍invoke没有初始化,第二遍有值了
Child invoke null; null
构造子类后,再调用invoke()方法时,由于子类的invoke()方法没有
pStr = "Parent pStr";
这句,所以打印第二条就为
Child invoke child cStr; null在一个类实例化时,会首先调用其父类的构造方法,才会调用自己的构造方法。
protected String pStr; public Parent() {
invoke();
}
public Parent(String name) {
System.out.println(name);
} public void invoke() {
System.out.println("Parent invoke " + pStr);
pStr = "Parent pStr";
}
}public class Child extends Parent {
private String cStr; public Child() {
super("parent");
} public void invoke() {
System.out.println("Child invoke " + cStr + "; " + pStr);
cStr = "child cStr";
} public static void main(String[] args) {
Child c = new Child();
c.invoke();
}
}当父类只有有参构造方法时,这个显式调用是必须的。
parent
Child invoke null; null
动态绑定是相对于静态绑定(又称编译器绑定)而言的,java根据动态绑定决定一个方法的调用是调用哪个类的方法。如:
Father f = new Son();
f.someMethod();
jvm如何解析这段调用someMethod的代码?首先jvm要确定方法调用的主体,即使调用了哪个类的someMethod方法。这点由JTTI支持,java中每个对象的对象头都会存有该对象的类型,对于上面的例子,存的就是com.eros.Son。此时jvm就会关联f对象和Son.someMethod方法。这就是继承的原理。
何时会执行动态绑定?
参见http://docs.oracle.com/javase/specs/中invokeSpecial和invokeVirtual指令。
理解了以上几点几能很快搞清楚你的问题了,
首先Cliend c = new Child();
java中构造实例对象前会先递归检查有没有父类,并依次调用父类的构造函数。故会去执行父类构造器,并调用其内的invoke方法,根据上面的分析,invoke方法的调用主体是谁?是this!
public Parent() {
this.invoke();
}
这段代码跟你的构造器是一样的。
如果我们在这段代码之前加一句System.out.println(this.getClass());
你会发现结果是class question.Child。
ok,接下来就是动态绑定的事了。
c.invoke同理
相关refer:
对象头:http://www.iteye.com/topic/1113318
this关键字:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.3
它会去执行Child类中的构造函数
public Child() {
super();
}
当它执行到super的时候,就会去执行父类中的Parent的构造函数,然后执行Parent中的invoke()方法.
执行完后再回来执行Child类中的c.invoke()方法.
我想你应该想知道为继承的时候会有一次执行交类构造函数,super的时候也会执行一次父类的构造函数,而这里却只执行了一次是吧.
原因:如果Child类中有重写的构造方法,那么先执行父类的构造方法,再执行Child类的构造方法.
原因二:因为Child类中有一个super()函数,这个函数只能放在构造函数的第一行,如果放第二行会报错.
也就是因为这两个原因,才会使得父类方法只执行了一次,当然重点还是因为原因二,你只要记得它的用法就可以了,也算是一个规则性的东西.
class Parent {
protected String pStr;
public Parent() {
System.out.println(this.getClass().getName());
invoke();
}
public void invoke() {
System.out.println("Parent invoke " + pStr);
pStr = "Parent pStr";
}
}
public class Child extends Parent {
private String cStr;
public Child() {
super();
}
public void invoke() {
System.out.println("Child invoke " + cStr + "; " + pStr);
cStr = "child cStr";
}
public static void main(String[] args) {
Child c = new Child();
c.invoke();
}
}
,pStr为null你应该懂得吧这是我的理解,有不对的地方请指正!
invoke();
<=>
this.invoke();关键是这个this指谁。