第八章多态

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(继承)时才被容许。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.第八章一开头就说了多态的作用:消除类型之间的耦合关系。 2.多态的前提是继承与重写,因为继承之后允许将子类视为...
    Gzw丶南山阅读 2,839评论 0 0
  • 多态分离做什么和怎么做,将接口和实现分离开来。也称为动态绑定、后期绑定或运行时绑定。
    MAXPUP阅读 1,184评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,597评论 18 399
  • 这两天正好读到易中天先生的《帝国的惆怅》中一开篇就讲述了关于晁错的故事,该篇章的标题更有意思,叫做“明月何曾照沟渠...
    正言锋语阅读 1,670评论 0 1
  • 最近一篇网文《罗振宇的骗局》炒的沸沸扬扬,很多人纷纷痛彻心扉,自诉自己花钱学习却没有什么卵用。 关于知识的结构太多...
    中大猩猩阅读 3,624评论 4 2

友情链接更多精彩内容