Overview
最近在学习Thinking in Java这部java经典,书非常不错,作者有非常深厚的编程功底,讲解知识时候说的很透彻,而且有一定发散,深入浅出,是一本阅读起来非常舒服。目前阅读到第八章,除了第五章初始化与清理里的垃圾回收机制有些难度以外,其他章节有一定编程经验的都可以看懂。从第八章开始,内容开始增多,各种重要知识点开始出现,如不好好总结很可能会漏掉一些细节,所以从这里开始对第八章进行总结。
有关垃圾回收的知识我准备在以后在整理jvm相关知识时再做详细总结。
Contents
-
初始化的顺序
- 先将分配给对象的存储空间初始化成二进制的零。
- 调用基类的构造器。这个步骤一直递归下去,直至递归到根类,再开始从根向导出类开始初始化。
- 按声明顺序调用成员的初始化方法。
- 调用导出类构造器的主体。
初始化的顺序还要注意在第五章中提到的知识,静态对象要先于非静态对象。
- 构造器内部的多态方法的行为
class Super {
public int field = 0;
public int getField() {
return field;
}
}
class Sub extends Super {
public int field = 1;
public int getField() {
return field;
}
public int getSuperField() {
return super.field;
}
}
public class JavaTest{
public static void main(String[] args) {
Super sup = new Sub(); //向上转型
//这里在直接访问域的时候,并没有出现理想中的多态
System.out.println("sup.field: " + sup.field + "\nsup.getField: " + sup.getField() + "\n");
Sub sub = new Sub();
System.out.println("sub.field: " + sub.field + "\nsub.getField: " + sub.getField() + "\nsub.getSuperField():" + sub.getSuperField());
}
}
输出为:
sup.field: 0
sup.getField: 1
sub.field: 1
sub.getField: 1
sub.getSuperField():
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,由于多态采用的是动态绑定,而不是靠编译器,所以无法完成多态。
在上面的例子中,一个sub对象中有两个叫做field的域(Super.field和Sub.field),然而在引用sub中的field时所产生的默认域并非Super版本的field,因此必须显示的指明super.field。
在实际编程中非常不赞成出现这样的代码,这样的代码难以阅读,进而难以维护。
public class Test1 {
public void printStr(String s){
System.out.println("this is test1.printStr");
System.out.println(s);
}
public void printStr2(String s){
printStr(s);
}
}
public class Test2 extends Test1 {
public void printStr(String s){
System.out.println("this is test2.printStr");
System.out.println(s);
}
public static void main(String[] args) {
Test1 test = new Test2();
test.printStr2("test");
}
}
输出为:
this is test2.printStr
test
这是第八章练习10的运行效果,和上面的结果放在一起对比看起来会更佳直观,这里的printStr()方法被覆盖了,即使是Test1的方法调用printStr()也会调用被覆盖的方法,与上面的变量覆盖是不同的。
-
构造器内部的多态方法的行为
- 在Java1.4及以前,子类方法如果要覆盖超类的某个方法,必须具有完全相同的方法签名,包括返回值也必须完全一样。
- Java5.0放宽了这一限制,只要子类方法与超类方法具有相同的方法签名,或者子类方法的返回值是超类方法的子类型,就可以覆盖。
- 注意:"协变返回(covariant return)",仅在subclass(子类)的返回类型是superclass(父类)返回类型的extension(继承)时才被容许。
网友评论