20172301 2017-2018-2 《程序设计与数据结构》第八周学习总结

20172301 2017-2018-2 《程序设计与数据结构》第八周学习总结

教材学习内容总结

  • 多态:有许多形式,能在不同的时间指向不同类型的对象。
    • 多态的体现:父类的引用指向了自己子类的对象。
    • 多态的前提:类与类之间要存在继承或者是实现关系,并且存在覆盖
    • 多态的好处:提高代码的复写性。
  • 后绑定(静态绑定):延迟到程序运行时才能执行。
  • 建立多态方式的两种方式:继承接口
    • 注意:继承方式中,实际将调用的方法版本取决于对象的类型而不是引用对象的类型。
      接口方式中,实际调用的方法不是取决于接口引用的类型,而是取决于调用发生时接口引用所指向的对象的类型
    • 同样注意:在使用接口引用变量时,只能调用定义在接口中的方法。即使接口引用变量所指向的对象还有其他的一些方法,也不能调用。
      这跟继承多态是不同的。继承多态是可以调用子类的方法。所以,只能在一定意义上说,实现类与所实现的接口的关系,如同子类和父类的关系。
  • 使用多态性解决的两种问题:排序搜索
  • 排序:
    • 选择法排序:扫描数列,找到最小的一个和第一个进行交换。
    • 插入法排序:逐渐比较几个数之间的大小,如果有变化,那么将把小的数插入到前面,其他的向后移动。
    • 比较:选择法排序和插入法排序实质上有同等的效率,都是n^2算法。但是,选择法排序执行的交换操作的次数更少。因此选择法优于插入法
  • 搜索:
    • 线性搜索:从起点开始,一个个进行搜索,最终找到目标。
    • 二分搜索:必须是有序的。不断的取中点进行搜索。如果搜索个数是偶数,那么就会有两个中点。取第一个中点为新的中点。
    • 比较:算法的选择取决于具体条件
      二分搜索适用于数据排序相对容易或者数据的搜索量非常大线性搜索的实现相对简单,虽然效率比较低,但是在一些忽略效率的问题上是最佳选择。
  • 多态性设计:培养自己的设计敏感性,知道什么问题能够运用多态性解决。提高代码的复写性。不同类型的对象执行相同类型的方法。

教材学习中的问题和解决过程

  • 问题1:后绑定(动态绑定)和静态绑定。

  • 问题1解决方案:这里先给出一个参考链接:关于多态以及动态绑定

    • 如果对多态的定义和优点还有困惑,这篇博客里面给出了更加形象具体的解释。

    多态就是同一事物的多种不同形态,简单点来说就是:“一个接口,多种实现”。

    举个例子:体育课上体育老师只要喊一句:“开始活动”,则 打篮球的就开始打篮球,踢足球的就开始踢足球,体育老师不用对打篮球的喊“开始打篮球”,对踢足球的喊“开始踢足球”,即学生是一个“抽象”的事物,只要是学生就具备活动的能力,所以只要喊“开始活动”,则学生就会开始活动,至于活动的内容,则有不同的学生内部自己去实现去决定。
    这就使事情变得十分灵活了,即实际上多态让“做什么”和“怎么做”分离了,即体育老师只要发布“做什么”(一个接口),而学生可以去具体做各自的事“怎么做”(多种实现)。这就是多态的优点。所以我们看出只要存在继承,并且父类子类之间存在重写方法,则就存在多态。

       同样,多态的前提在文中也有提及。

    • 现在我们来解释动态绑定和静态绑定。首先我们要清楚他们的定义。
      静态绑定(前期绑定):即在程序执行前,即编译的时候已经实现了该方法与所在类的绑定。
      动态绑定(后期绑定)运行时根据对象的类型进行绑定,java中的大多数方法都是属于动态绑定,也就是实现多态的基础。

       这里所谓的绑定,即一个方法的调用与方法所在的类(方法主体)关联起来。

       java中只有staticfinal,private构造方法静态绑定,其他的都属于动态绑定,而private的方法其实也是final方法(隐式),而构造方法其实是一个static方法(隐式)。
    所以可以看出把方法声明为final,第一可以让他不被重写,第二也可以关闭它的动态绑定。

    • 实现动态绑定一个很重要的东西就是在jvm方法区里每一个类都有一个方法表(实质是一个数组),这个方法表里记录了这个类的所有方法(包括继承父类的方法)在内存里的地址

    我们来看个例子:

    Father fa=new Son();
    fa.say();

    可以看到这就是一个多态,他的执行结果应该是调用Son里面的say()方法,但是他是如何准确找到Son中的say()方法呢。

    • 具体过程是,

      • 首先由于fa的类型是Father,所以一开始还是会到Father类的方法表里去找say()方法
      • 然后获得到say()方法的索引项比如是第N项(即在方法表里的位置),如果此时Father的方法表里找不到say()方法那就直接编译报错了
      • 得到say()在Father里的索引项之后,然后根据堆里new的具体实例的类型(这里是Son),去Son里面的第N项取出say()方法在内存里的地址,然后执行。
      • 如果想继续了解JVM如何调用的方法。请参考资料:
        Java动态绑定机制原理分析
    • 结合书上所见,后绑定的效率低于编译阶段的绑定效率。但是,明显的优点就是实现了多态。

  • 问题2:对象和引用变量。他们两个之间怎么区别?这个问题,一开始是方艺雯同学问我书上的creature是引用变量吧。当时只是暂时解决了,然后,我回去把这个问题抛给了组员李馨雨同学。结果把刚刚看完10.2的她又给弄懵了。( ̄▽ ̄)~*

  • 问题2解决方案:

    对象:是按照“类”这个模板建立的,建立的位置则是内存
    例如A是一个类。A X则是创建一个引用变量,X=NEW A()则是在内存中建立一个对象(开辟了1片空间),对象的模板就是A(可以理解为在空间里复制了A类里的变量到空间里去)。
    此时就可以使用引用变量X去引用对象中的变量了

    这句话确实说的确实有点模糊。但是在细细琢磨一下,好像似懂非懂。我说下我自己的理解。引用变量,就是在内存中为对象开辟的一个空间。它指向的是对象。并不是对象本身。

    • 那么,我们来继续探讨。Java对象及对象引用变量
      我们一般创建对象。都是Vehicle veh1 = new Vehicle();
      现在把它分成两部分,
Vehicle veh1;  
veh1 = new Vehicle();
有两个实体:一是*对象引用变量*,一是*对象本身*。
 Vehicle veh2;  
 veh2 = veh1; 
这时候,veh2指向了veh1所指向的对象。**复制的是对象引用,而非对象本身。**  
所以,有以下<span style="color:purple">**结论**</span>:  

一个对象引用可以指向0个或1个对象
一个对象可以有N个引用指向它

如果还不清楚,我们进一步研究。[Java对象和引用变量](https://blog.csdn.net/weixin_35813749/article/details/52374749)  
存储区域 存储内容 优点 缺点 回收
基本类型的变量和对象的引用变量 存取速度比堆要快,仅次于寄存器,栈数据可以共享 存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量 当超过变量的作用域后,Java会自动释放掉该变量,内存空间可以立即被另作他用
由new等指令创建的对象和数组 可以动态地分配内存大小,生存期也不必事先告诉编译器 由于要在运行时动态分配内存,存取速度较慢 由Java虚拟机的自动垃圾回收器来回收不再使用的数据

   我们可以观察到,引用变量是存在栈内存中的。
   那么我们就可以得出 结论

引用变量就相当于是为数组或对象起的一个名称,可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

   引用变量起到的就是指针的作用,指向堆内存的对象实例。
   我们结合上面的例子来总结一下,

Vehicle veh1;  
veh1 = new Vehicle();

   首先, new Vehicle()在堆内存里面开辟了空间给Vehicle类的对象,这个对象没有名字
   然后, Vehicle()随即调用了Vehicle类的构造函数
   最后, 把对象的地址在堆内存的地址给引用变量veh1

   ヾ(๑╹◡╹)ノ" 终于是懂了。

  • 问题3:向上转型和向下转型的区别和有关困惑。这个概念是在视频里面提到了,在周测里面也有涉及。所以研究下。
  • 问题3解决方案:
    • 我先看见了一个这个问题,java多态向上转型向下转型的问题
      为什么不叫做子类引用指向父类对象呢?
      我觉得这个问题很有意思,为什么就偏偏叫做父类引用指向子类对象呢?
      结合上个问题,我们应该能很容易回答。如果是子类引用指向父类对象 Cat a = new Animal();这显然是不合逻辑的。
    • 现在回归正题。区别一下两个用法,
      向上转型:只能调用与父类引用中父类相同的方法,++不能调用子类中自己定义的方法++;如果在子类中重写了,则调用的是子类中的方法;
      向下转型:可以调用父类中的方法,++也可以调用子类中自己定义的方法++;如果子类中重写了父类的方法,调用的是子类中重写的方法;
    • 对象间的转型问题:
      向上转型:
      Fu f = new Zi();
      向下转型:
      Zi z = (Zi)f;//要求该f必须能够转换为Zi的。
      由此我们可见,向上转型是自动的,而向下转型则是强制的。 可以自己编写代码尝试一下。
    • 参考资料:

代码调试中的问题和解决过程

  • 问题1:在做项目10.5的时候,排序有点问题。

  • 问题1解决方法:实际上呢,是我对排序算法的理解还不够深入。这个应该是对DVDCollection类进行排序,我们应该重新定义这个类,并且重写构造方法。并且实现接口Comparable重写compareTo方法

代码托管

上周考试错题总结

  • Which of the following is true regarding Java classes? : A
    A . All classes must have 1 parent but may have any number of children (derived or extended) classes
    B . All classes must have 1 child (derived or extended) class but may have any number of parent classes
    C . All classes must have 1 parent class and may have a single child (derived or extended) class
    D . All classes can have any number (0 or more) of parent classes and any number of children (derived or extended) classes
    E . All classes can have either 0 or 1 parent class and any number of children (derived or extended) classes
    理解:java是单继承,所以肯定只有一个父类。但是不要忘记Object类,所有类间接或者直接都是它的子类。所以每个类必须有一个父类,而子类就可以若干了。这里不要钻牛角尖,说什么Object类的父类是谁。

  • A variable declared to be of one class can later reference an extended class of that class. This variable is known as : D
    A . protected
    B . derivable
    C . cloneable
    D . polymorphic (多态)
    E . none of the above, a variable declared to be of one class can never reference any other type of class, even an extended class
    理解:这里我们首先要清楚polymorphic是多态的意思。结合第十章的知识,我们就可以很好的理解这道题。多态引用变量可以指向不同类型的对象。

  • Abstract methods are used when defining : A
    A . interface classes
    B . derived classes
    C . classes that have no constructor
    D . arrays
    E . classes that have no methods
    理解:抽象方法什么时候被定义?第一种就是在抽象类里面,另一种就是接口里面。这道题我看到E的时候直接就认为没有方法体的方法就是抽象方法。实际上,是因为我英语阅读的错误。这也是追求速度的弊端。没有认真查阅题目。

结对及互评

点评过的同学博客和代码

  • 本周结对学习情况
    • 20172304
    • 希望段志轩同学的博客能稍微再详细一些。
    • 20172328
    • 李馨雨同学的博客这次没有只通过机翻,而自己进行了审查。在参考链接给出了如何控制心态。但是,注意博客园的markdown语法和其他的一般有的是不兼容的。比如博客中的“++XXX++”在有道云应该是下划线,但是在博客园中是无法显示的。

其他

这周的学习很紧张。因为有一个小组任务,四则运算。所以说,第十章的理解并不是足够的全面。在周测的答题时间上我对自己进行了控制,尽量保持一道题在一分钟左右,对于单词比较复杂的题目用时可能较多。学长说,应该少扣概念,而加强对代码的运用编写。这一章的多态要有足够的设计敏感性,要知道什么时候运用多态,更好的解决代码重复问题。这一点,应该有意识的锻炼自己
学会控制自己的压力,保持良好的心态和动力。不能因为一点挫折而郁郁不振。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 122/122 1/1 20/20
第二周 487/609 1/2 18/38
第三周 482/1091 1/3 22/60
第四周 1357/2448 1/4 20/80
第五周 628/3106 1/5 20/100
第六周 566/3672 2/7 20/120
第七周 934/4606 1/8 25/145
第八周 2407/7013 1/9 30/175

参考资料

posted @ 2018-05-02 20:23  奈何明月ઇଓ  阅读(262)  评论(2编辑  收藏  举报
页尾