第十章 多态性:
- 后绑定: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来; 在java中,绑定分为静态绑定(前期绑定)和动态绑定(后期绑定);前期绑定: 在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由编译器或其它连接程序实现;注: java当中的方法只有final,static,private和构造方法是前期绑定;后期绑定: 在运行时根据具体对象的类型进行绑定;
- 优点:灵活性强
- 缺点:效率较低(判断类型过程)
由继承实现多态性: 引用变量可以指向有继承关系的任何类的任何对象;但在调用方法时,
利用接口实现多态性:
接口名可以声明对象引用变量
声明接口: public interface Speaker { public void speak(); public void announce(String str); }
声明对象引用变量(可指向实现该接口任何类的任何对象) Speaker current;
实现类与接口之间有一种“是”的关系;
在调用方法时,实际调用的取决于 调用发生接口引用所 指向的对象类型; 在使用接口引用变量时,只能调用定义在接口里的方法, 若尝试调用实现接口类里的其他方法会产生编译时错误 (编译器只能确定类对象是一种Speaker); 适当的类型转换可以实现调用:((实现接口的类)接口引用变量).方法名()
接口名可做方法参数类型,实现同一接口的类对象可作为 参数传递给方法。
- 排序: 将一组元素调整为有序排列的过程
- (1)选择法排序: 原理: 1、从第一个元素开始,分别与后面的元素向比较,找到最小的元素与第一个元素交换位置; 2、从第二个元素开始,分别与后面的元素相比较,找到剩余元素中最小的元素,与第二个元素交换; 3、重复上述步骤,直到所有的元素都排成由小到大为止。 例子:
待比较数据:7, 6, 9, 8, 5,1 第一轮:此时指针指向第一个元素7,找出所有数据中最小的元素,即1,交换7和1的位置,排序后的数据为:1,6,9,8,5,7 第二轮:第一个元素已经为最小的元素,此时指针指向第二个元素6,找到6,9,8,5,7中最小的元素,即5,交换5和6的位置,排序后的结果为:1,5,9,8,6,7 第三轮:前两个元素为排好序的元素,此时指针指向第三个元素9,找到9,8,6,7中最小的元素,即6,交换6和9的位置,排序后的结果为:1,5,6,8,9,7 第四轮:前三个元素为排好序的元素,此时指针指向第四个元素8,找到8,9,7中最小的元素,即7,交换8和7的位置,排序后的结果为:1,5,6,7,9,8 第五轮:前四个元素为排好序的元素,此时指针指向第五个元素9,找到9,8中最小的元素,即8,交换9和8的位置,排序后的结果为:1,5,6,7,8,9到此,全部排序完成。
- (2)插入法排序: 原理: 1、将指针指向某个元素,假设该元素左侧的元素全部有序,将该元素抽取出来,然后按照从右往左的顺序分别与其左边的元素比较,遇到比其大的元素便将元素右移,直到找到比该元素小的元素或者找到最左面发现其左侧的元素都比它大,停止; 2、此时会出现一个空位,将该元素放入到空位中,此时该元素左侧的元素都比它小,右侧的元素都比它大; 3、指针向后移动一位,重复上述过程。每操作一轮,左侧有序元素都增加一个,右侧无序元素都减少一个。 例子:
待比较数据:7, 6, 9, 8, 5,1 第一轮:指针指向第二个元素6,假设6左面的元素为有序的,将6抽离出来,形成7,_,9,8,5,1,从7开始,6和7比较,发现7>6。将7右移,形成_,7,9,8,5,1,6插入到7前面的空位,结果:6,7,9,8,5,1 第二轮:指针指向第三个元素9,此时其左面的元素6,7为有序的,将9抽离出来,形成6,7,_,8,5,1,从7开始,依次与9比较,发现9左侧的元素都比9小,于是无需移动,把9放到空位中,结果仍为:6,7,9,8,5,1 第三轮:指针指向第四个元素8,此时其左面的元素6,7,9为有序的,将8抽离出来,形成6,7,9,_,5,1,从9开始,依次与8比较,发现8<9,将9向后移,形成6,7,_,9,5,1,8插入到空位中,结果为:6,7,8,9,5,1 第四轮:指针指向第五个元素5,此时其左面的元素6,7,8,9为有序的,将5抽离出来,形成6,7,8,9,_,1,从9开始依次与5比较,发现5比其左侧所有元素都小,5左侧元素全部向右移动,形成_,6,7,8,9,1,将5放入空位,结果5,6,7,8,9,1。 第五轮:同上,1被移到最左面,最后结果:1,5,6,7,8,9。
(3)排序算法的比较:
二者实质上效率一样,均为n²阶算法,但前者所执行的交换操作次数更少,优于后者。- 搜素: 在一组元素中寻找一个指定的目标元素的过程
- (1)线性搜素:从一个端点开始,以线性的方式扫描整个搜索池,最终找到或搜索至终点发现不存在目标元素。
(2)二分搜索:
在数组有序的情况下,效率高于线性搜索; 原理: 假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。(3)搜素算法的比较:
二分搜索需要数据做过排序,搜索算法的选择取决于具体条件。多态性设计:
允许用一致性的方法实现不一致的行为,应更合理地定义类与对象,建立起适当的关联,以提高软件的灵活性。
- 问题1: 什么是向上转型与向下转型?
- 解决:向上转型: 子类引用的对象转换为父类类型称为向上转型,通俗地说就是是将子类对象转为父类对象,父类对象也可以是接口。 eg:
public class Animal { public void eat(){ System.out.println("animal eatting..."); }}public class Cat extends Animal{ public void eat(){ System.out.println("我吃鱼"); }}public class Dog extends Animal{ public void eat(){ System.out.println("我吃骨头"); } public void run(){ System.out.println("我会跑"); }}public class Main { public static void main(String[] args) { Animal animal = new Cat(); //向上转型 animal.eat(); animal = new Dog(); animal.eat(); }}//结果://我吃鱼//我吃骨头
Animal animal = new Cat();将子类对象Cat转化为父类对象Animal。这个时候animal这个引用调用的方法是子类方法。
注意事项: 向上转型时,子类单独定义的方法会丢失。比如上面Dog类中定义的run方法,当animal引用指向Dog类实例时是访问不到run方法的,animal.run()会报错。 优点: 使代码更加简洁。eg:有着一群不同种类动物,我要定义它们吃的方法
没有使用向上转型:public void eat(Cat c){ c.eat();}public void eat(Dog d){ d.eat();}//......eat(new Cat());eat(new Cat());eat(new Dog());//......
倘若有上万种,我得给每一只都写一个吃的方法 这不得累死!
public void eat(Animal a){ a.eat();}eat(new Cat());eat(new Cat());eat(new Dog());//.....
即使后面再有其它种类的动物加进来,只需让它去实现自己的类,继承Animal就可以了,这样无疑使得编码的效率高了许多。
向下转型:
简单啊,与前面相反嘛,把父类对象转为子类对象 先来看个例子://animal和cat dogAnimal a = new Cat();Cat c = ((Cat) a);c.eat();//输出 我吃鱼Dog d = ((Dog) a);d.eat();// 报错 Animal a1 = new Animal();Cat c1 = ((Cat) a1);c1.eat();// 报错
为什么会报错??? a本身就是Cat对象,所以它当然可以向下转型为Cat,不能转为Dog;
而a1为Animal对象,你不知道是猫还是狗,当然无法完成转型 注意事项: 向下转型的前提是父类对象指向的是子类对象,即:Animal a = new Cat()
或 Animal a = new Dog()
只能转型为本类对象(即猫为猫,狗为狗,猫!=狗) 问题1:项目PP10.4,
解决:一开始拿到手,(⊙o⊙)… 看下原代码,
声明的是min,咦哟!这么简单的咯,匡匡的就把min全改为max,这么快,这东西有点简单咯!然而: emmm,很显然,并没有作对。降序啊,min变为max,很有道理的啊!然而,经过一番 不过是将变量名换了,对程序的操作并没有丝毫影响。 认真看了之后,发现了问题所在, 果然编程还是要从代码入手,而不是惯性思维地改个变量名就行了
错题1:
理解:Object类很特殊,Java不支持多重继承,所有的子类都直接或间接从Object类继承,且它们可有任意多个子类。
错题2:
理解:保留字super提供了访问父类的方法和实例数据的机制(无论其是否隐藏),也可用来访问父类的构造函数。
错题3:
理解:当类用final修饰,则其不能扩展。
错题4:
理解:子类可以重新定义父类的实例数据及方法,即使被隐藏,也可通过super来对其访问。
- 本周结对学习情况:
- 博客中值得学习的或存在问题: 1.
问题1解决方案:查找网上类似的问题,得到一点启发
可以将类似的问题呈现出来 2.教材内容总结简洁明了 3.第一段参考资料无链接。 - 博客中值得学习的或存在问题: 1.部分地区应适当地缩进; 2.问题1、3里的文字过于亢长,如果有适当的例子加上个人理解会更好; 3.css样式很精美。
- 拿到问题,不能匡匡地一顿乱敲,要先认真分析,对症下药,就像先想好UML图才能去编写代码一样,两眼抹黑一顿乱敲,浪费了时间不说,敲出来的还不是自己想要的。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 202/202 | 1/2 | 15/15 | 积极主动敲代码 |
第二周 | 490/692 | 1/3 | 18/33 | 善于思考 |
第三周 | 581/1273 | 1/4 | 15/48 | 善于完善 |
第四周 | 1857/3130 | 1/6 | 33/81 | 累 |
第五周 | 655/3787 | 1/7 | 22/103 | |
第六周 | 531/4318 | 1/8 | 18/121 | |
第七周 | 810/5128 | 1/9 | 23/ 144 | |
第八周 | 698/5826 | 1/13 | 21/ 165 |