`
凌紫冥
  • 浏览: 25652 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java编程思想第四版——第二天

    博客分类:
  • Java
 
阅读更多
今天本来以为进度可以快点,但是没想到这么慢,只是今天的知识点比较多。
41-47
多态:
极大的改善我们的设计,同时也降低软件维护的代价。

面向对象程序设计的最重要的妙诀:
编译器不可能产生传统意义上的函数调用。
一个非面向对象编程的编译器产生的函数调用会引起所谓的前期绑定。这么做意味着编译器将产生对一个具体函数名字的调用,而运行时将这个调用解析到将要被执行的代码的绝对地址。在OOP中,程序直到运行时才能够确定代码的地址,所以当消息发送到一个泛化对象时,必须采用其他的机制。
为了解决这个问题,面向对象程序设计语言使用了后期绑定的概念。当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查(无法提供此类保证的语言成为是弱类型的),但是并不知道将被执行的确切代码。
为了执行后期绑定,java使用一小段特殊的代码来替代绝对地址调用。这段代码使用在对象中存储的信息来计算方法体的地址(这个过程在第八章中详述)。这样,根据这一小段代码的内容,每一个对象都可以具有不同的行为表现。当向一个对象发送消息时,该对象就能够知道对这条消息应该做些什么。
C++使用virtual关键字实现某个方法具备后期绑定属性,java中动态绑定时默认行为,不需要额外的关键字来实现多态。

将子类看做是它的父类的过程称为向上转型(upcasting)。
转型(cast)这个名称的灵感来自于模型铸造的塑模动作,而向上(up)这个词来源于继承图的典型布局方式:通常父类在顶部,而子类在其下部散开。因此转型为一个父类就是在继承图中向上移动,即“向上转型”。


一个面向对象程序肯定会在某处包含向上转型,因为这正是将自己从必须知道确切类型中解放出来的关键。

单根继承机构:在OOP中,自C++面世以来就已变得非常瞩目的一个问题就是,是否所有的类最终都继承自单一的基类。在java中(事实上还包括除C++以外的所有OOP语言)。答案是YES,这个终极基类的名字就是Object。
单根继承机构带来的好处:在单根继承机构中的所有对象都具有一个共用接口,所以它们归根到底都是相同的基本类型。C++提供的机构无法确保所有对象都属于同一个基本类型。从向后兼容的角度看,这么做能够更好地适应C模型,而且受限较少,但是当要进行完全的面向对象程序设计时,则必须构建自己的继承体系,使得它可以提供其他OOP语言内置的便利。
单根继承结构保证所有对象都具备某些功能。可以在每个对象上执行某些基本操作,所有对象都可以很容易的在堆上创建,参数传递也得到了极大的简化。
单根继承结构使垃圾回收器的实现变得容易的多,而垃圾回收器正是java相对C++的重要改进之一。

容器:(java类库以不同的含义使用“集合”这个术语)持有对其他对象的引用,在任何需要时都可以扩充自己以容纳置于其中的所有东西,不需要知道将来会把多少个对象置于容器中,只需要创建一个容器对象,然后然它处理所有细节。
不同容器提供了不同类型的接口和外部行为。例如:堆栈相比于队列就具备不同的接口和行为,也不同于集合和列表的接口和行为。
不同的容器对于某些操作具有不同的效率。最好的例子:两种List的比较,ArrayList和LinkedList。ArrayList中,随机访问元素是一个花费固定时间的操作,LinkedList随机选取元素需要在列表中移动,这种代价是高昂的,访问越靠近表尾的元素,花费的时间越长。在序列中间插入一个元素,LinkedList的开销比ArrayList要小。上述操作及其他操作的效率,依序列底层结构的不同而存在很大的差异。实际运用:可以在一开始使用LinkedList构建程序,在优化系统性能时改用ArrayList。接口List所带来的抽象,把在容器之间进行转换时针对代码产生的影响降到最小限度。

1.9.1 参数化类型
在java SE5之前,容器存储的对象都只具有java中德通用类型:Object。单根继承结构意味着所有东西都是Object类型,所以可以存储Object的容器可以存储任何东西,这使得容器很容易被复用。
取回容器中的对象,需要用到转型,向下转型为更具体的类型,向下转型。向上转型时安全的,除非确切知道所要处理的对象的类型,否则向下转型几乎时不安全的。
参数化类型:知道自己所保存的对象的类型,从而不需要向下转型以及消除犯错误的可能。参数化类型就是一个编译器可以自动定制作用于特定类型上的类。
Java SE5的重大变化之一就是增加了参数化类型,在java中它称为泛型。一对尖括号,中间包含类型信息,通过这些特征就可以识别对泛型的使用。为了利用泛型的优点,很多标准类库构件都已经进行了修改。

1.10 对象的创建和生命期
使用对象时,最关键的问题之一便是它们的生成和销毁方式。
C++认为效率控制最重要,所以给了程序员提供选择的权利。为了追求最大的执行速度,对象的存储空间和生命周期都可以在编写程序时确定,这可以通过将对象置于堆栈(它们有时被称为自动变量(automatic variable)或限域变量(scoped variable))或静态存储区域内来实现。这种方式将存储空间分配和释放置于优先考虑的位置,牺牲了灵活性。
第二种方式时在被称为堆(heap)的内存池中动态地创建对象。这种方式,直到运行时才知道需要多少对象,它们的生命周期如何,以及它们的具体类型是什么,这些问题的答案只能在程序运行时相关代码被执行到的那一刻才能确定。存储空间是在运行时被动态管理的,所以需要大量的时间在堆中分配存储空间,这可能要远远大于在堆栈中创建存储空间的时间。
Java完全采用了动态内存分配方式,当想要创建新对象时,就要使用new关键字来构建此对象的动态实例。
生命周期:对于允许在堆栈上创建对象的语言,编译器可以确定对象存活的时间,并可以自动销毁它。如果是在堆上创建对象,编译器就会对它的生命周期一无所知。C++中必须通过编程方式来确定何时销毁对象,这可能会因为不能正确处理而导致内存泄漏。Java提供了“垃圾回收器”的机制,可以自动发现对象何时不再被使用,并销毁它。可以避免暗藏的内存泄漏问题。
Java的垃圾回收器被设计用来处理内存释放问题(不包括清理对象的其他方面)。垃圾回收器“知道”对象何时不再被使用,自动释放对象占用的内存。这一点同所有对象都是继承自单根基类Object以及只能以一种方式创建对象(在堆上创建)这两个特性结合起来,使用java编程的过程比C++编程要简单的多,所要做出的决策和要克服的障碍也要少得多。

1.11 异常处理:处理错误
自从编程语言问世以来,错误处理就始终是最困难的问题之一。
异常处理是一种对象,它从出错地点被“抛出”,被专门设计用来处理特定类型错误的相应的异常处理器“捕获”。异常处理就像是与程序正常执行路径并行的、在错误发生时执行的另一条路径。因为它是另一条完全分离的执行路径,所以它不会干扰正常的执行代码。
Java一开始就内置了异常处理,而且强制你必须使用它。它是唯一可接受的错误报告方式,没有编写正确的处理异常的代码,就会得到一条编译时的出错消息。
异常处理不是面向对象的特征,在面向对象语言出现之前就已经存在了。

1.12 并发编程
在计算机编程中有一个基本概念,就是在同一时刻处理多个任务的思想。
  • 大小: 6.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics