1.1抽象过程
1.2每个对象都有一个接口
1.3每个对象都提供服务
1.4被隐藏的具体实现
1.5复用具体实现
1.6继承
1.6.1“是一个”与“像是一个”关系
1.7伴随多态的可互换对象
1.8单根继承结构
1.9容器
1.9.1参数化类型
1.10对象的创建和生命期
1.11异常处理:处理错误
1.12并发编程
1.13Web是什么
1.1抽象过程
纯粹的面向对象程序设计方式:
- 万物皆对象。将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它在自身上执行操作;
- 程序是对象的集合,它们通过发送消息来告知彼此所要做的。要想请求一个对象,就必须对该对象发送一条消息;
- 每个对象都有自己的由其他对象所构成的存储。即可以通过创建包含现有对象的包的方式来创建新类型的对象;
- 每个对象都拥有其类型。每个对象都是某个类(类型)的一个实例。每个类最重要的区别于其他类的特性就是“可以发送什么样的消息给它”;
- 某一特定类型的所有对象都可以接受同样的消息;
1.2每个对象都有一个接口
由于类描述了具有相同特性和行为的对象集合,所以一个类实际上就是一个数据类型。一旦类被建立,就可以随心所欲的创建类的任意个对象,然后去操作它们。
每个对象都只能满足某些请求,这些请求由对象的接口(interface)所定义,接口确定了对某一特定对象所能发出的请求,决定接口的便是类型。
1.3每个对象都提供服务
在开发程序时,可以将对象想象为“服务提供者”。程序本身为用户提供服务,它将通过调用其他对象提供的服务来实现这一目的,开发者的目标就是去创建能够提供理想的服务来解决问题的一系列对象。
1.4被隐藏的具体实现
可以将程序开发人员按照角色分为“类创建者”和“客户端程序员”。客户端程序员的目标是收集各种用来实现快速应用开发的类。类创建者的目标是构建类,这种类只向客户端程序员暴露必需的部分,而隐藏其他部分。
关于为什么要隐藏?
- 让客户端程序员无法触及他们不应该触及的部分–这些部分对数据类型的内部操作是必需的,但并不是用户解决特定问题所需的接口的一部分;
- 允许库设计者可以改变类内部的工作方式而不用担心会影响到客户端程序员
1.5复用具体实现
一旦类被创建并测试完,那么它就应该代表一个有用的代码单元。最简单的复用某个类的方式就是直接使用该类的一个对象,此外也可以将那个类的一个对象置于某个新的类中,我们称其为“创建一个成员对象”。新的类可以由任意数量、任意类型的其他对象以任意可以实现新的类中想要的功能的方式所组成。
1.6继承
“对象”本身就是十分方便的工具,使得你可以通过概念将数据和功能封装到一起,因此可以对问题空间的观念给出恰当的表示,而不用于受制于必须使用底层机器语言。这些概念用关键字class来表示,它们形成了编程语言中的基本单位。
当继承现有类型时,也就创造了新的类型。这个新的类型不仅包括现有类型的所有成员,而且更重要的是它复制了基类的接口。也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。由于通过发送给类的消息的类型可知类的类型,所以也就以为这导出类与基类具有相同的类型。
有俩种方法可以使基类与导出类产生差异:
- 直接在导出类中添加新方法;
- 改变现有基类的方法的行为,即“覆盖”,要想覆盖某个方法,可以直接在导出类中创建该方法的新定义即可,“此时,我正在使用相同的接口方法,但是我想在新类型中做些不同的事情”。
1.6.1“是一个”与“像是一个”关系
对于继承可能会引发某种争论:继承应该只覆盖基类的方法(而不添加在基类中没有的新方法)吗?如果这样做就意味着导出类和基类是完全相同的类型,因为它们具有完全相同的接口。结果可以用一个导出类对象来完全代替一个基类的对象。这可以视为“纯粹替代”。这种情况下的基类与导出类之间的关系是“is-a”关系。
但有时必须在导出类型中添加新的接口元素,这样也就扩展了接口。这个新的类型仍然可以替代基类,但是这种替代并不完美,因为基类无法访问新添加的方法。这种情况我们可以描述位“is-like-a”关系。新类型具有旧类型的接口,但是它还包含其他方法,所以不能说它们完全相同。
1.7伴随多态的可互换对象
在处理类型的层次结构时,经常想把一个对象不当做它所属的特定类型来对待,而是将其当作其基类的对象来对待。这使得人们可以编写出不依赖于特定类型的代码。
在“几何形”的例子中,方法操作的都是泛化的形状,而不关心它们是圆形、正方形、三角形还是其他什么尚未定义的形状。所有的几何形状都可以被绘制、擦除和移动,所以这些方法都是直接对一个几何形对象发送消息;它们不用担心对象将如何处理消息。
但是在试图将导出类型的对象当作其泛化基类型对象来看待时,会导致编译器在编译时不知道应该执行哪一段代码。为了解决这个问题,面向对象程序设计语言使用了后期绑定的概念,当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查(无法提供此类保证的语言被称为弱类型的),但是并不知道将执行的确切代码。为了执行后期绑定,Java使用一小段特殊的代码来替代绝对地址调用。这段代码使用在对象中存储的信息来计算方法体的地址。此处设计向上转型和向下转型,后期介绍。
1.8单根继承结构
在Java中,所有的类最终都继承自单一的基类,这个终极基类的名字就是Object,事实证明,单根继承结构带来了很多好处。
- 在单根继承结构中所有对象都具有一个共用接口,所以它们归根到底都是相同的基本类型,这样往往更加便利;
- 单根继承结构保证所有对象都具备某些功能,所有对象都可以很容易的在堆上创建,而参数传递也得到了极大地简化;
- 单根继承结构使垃圾回收器的实现变得容易很多;
1.9容器
通常来说,如果不知道在解决某个特定问题时需要多少个对象,或者它们将存活多久,那么就不可能知道如何存储这些对象。
对于面向程序设计中的大多数问题而言,解决方法是:创建另一种对象类型。这种新的对象类型持有对其他对象的引用,这个通常被称为“容器”,在任何时候时都可以扩充自己以容纳你置于其中的所有东西,因此不需要知道将来会把多少个对象置于容器中,只需要创建一个容器对象,然后让它处理所有细节。
在Java的标准类库中包含有大量的容器,且可以满足不同需要,例如List(用于存储序列),Map(也被称为关联数组,用来建立对象之间的关联),Set(每种对象类型支持有一个),以及诸如队列、树、堆栈等更多的构件。
为什么要对容器有所选择?
- 不同容器提供了不同类型的接口和外部行为,它们之中的某种容器提供的解决方案可能比其他容器要灵活的多;
- 不同的容器对于某些操作具有不同的效率;
1.9.1参数化类型
在Java SE5出现之前,容器存储的对象都只具有Java中的通用类型:Object。单根继承结构意味着所有东西都是Object类型,所以可以存储Object的容器可以存储任何东西,这使得很容易被复用。
要使用这样的容器,只需在其中置入对象引用,稍后还可以将它们取回。但是由于容器只存储Object,所以将对象引用置入容器时,它必须被向上转型为Object,因此它会丢失其身份。当把它取回时,就获取了一个对Object对象的引用,而不是对置入时的那个类型的对象的引用,所以如何才能将它变回先前置入容器中时具有实用接口的对象?
向下转型为更具体的类型,当从容器中取出对象引用时,必须要以某种方式记住这些对象究竟是什么类型,这样才能执行正确的向下转型。
然而,向下转型和运行时的检查需要额外的程序运行时间,能否创建这样的容器,它知道自己所保存的对象的类型,从而不需要向下转型以及消除犯错误的可能,==这种方案被称为“参数化类型机制”==参数化类型就是一个编译器可以自动定制作用于特定类型上的类。
在Java SE5中增加了参数化类型,也叫“范型”,一对尖括号,中间包含类型信息,通过这些特征就可以识别对范型的使用,例如:
ArrayList<Shape> shapes = new ArrayList<Shape>();
1.10对象的创建和生命期
在使用对象时,最关键的问题之一便是它们的生成和销毁方式。每个对象为了生存都需要资源,尤其是内存。当我们不再需要一个对象时,它必须被清理掉,使其占有的资源可以被释放和重用。
怎样才能知道何时销毁某些对象呢?
当处理完某些个对象之后,系统某个其他部分可能还在处理它,Java采用的是==”动态内存分配方式“==,即在被称为堆(heap)的内存池中动态的创建对象,每当想要创建新对象时,就要使用new关键字来构建此对象的动态实例。
还有一个议题–对象生命周期,Java提供了被称为”垃圾回收器“的机制,它可以自动发现对象何时不再被使用,并继而销毁它。
1.11异常处理:处理错误
异常处理将错误处理直接置于编程语言中,有时甚至置于操作系统重。异常是一种对象,它从出错点被”抛出“,并被专门设计用来处理特定类型错误的相应的异常处理器”捕获“。异常处理就像是与程序正常执行路径并行的、在错误发生时执行的另一条路径。异常不能被忽略,且提供另一种从错误状况进行可靠回复的途径,不再只是只能退出程序,而是可以进行校正,并恢复程序的执行。
1.12并发编程
在计算机编程中有一个基本概念,就是在同一时刻处理多个任务的思想。许多程序设计问题都要求,程序能够停下正在做的工作,转而处理某个其他问题,然后再返回主进程。
有时中断对于处理时间性强的任务是必需的,但是对于大量其他的问题,我们只是想把问题切分为多个可独立运行的部分(任务),从而提高程序的响应能力。在程序中,这些彼此独立运行的部分称为”线程“,上述概念被称为”并发“。
并发存在一个隐患:共享资源。如果有多个并行任务都要访问同一项资源,那么就会出现问题,因此必须在使用期间被锁定,整个过程是:某个任务锁定某项资源,完成其任务,然后释放资源锁,使其他任务可以使用这项资源。
1.13Web是什么
- 客户/服务器计算技术
客户/服务器系统的核心思想是:系统具有一个中央信息存储池,用来存储某种数据,它通常存在于数据库中,你可以根据需要将它分发给某些人员或机器集群; - Web就是一台巨型服务器
Web实际上就是一个巨型客户/服务器系统,但稍微差一点,因为所有的服务器和客户机都同时共存于同一个网络中。
Web浏览器包含了这样的概念:一段信息不经修改就可以在任意型号的计算机上显示。然而最初的浏览器仍然相当原始,浏览器不具备显著的交互性,而且它趋向于使服务器和Internet阻塞,因为浏览器只是一个观察器,它甚至不能执行最简单的计算任务。
为了解决这个问题,人们采用了各种不同的方法。首先,图形标准得到了增强,使得在浏览器中可以播放质量更好的动画和视频。剩下的问题通过引入在客户端浏览器中运行程序的能力就可以解决。这被称为“客户端编程”。