目录
名词解释
1.1 抽象过程
1.2 每个对象都有一个接口
1.3 每个对象都提供服务
1.4 被隐藏的具体实现
1.5 复用具体实现
1.6 继承
1.7 伴随多态的可互换对象
1.8 单根继承
1.9 容器
1.10 对象的创建和生命期
1.11 异常处理:处理错误
1.12 并发编程
1.13 Java与Internet
解空间:对问题建模的地方,如计算机
问题空间:问题存在的地方,如一项业务
内置类型:在设计初期定义的类型,如基本数据类型int、float,如引用类型String
构件:构件是指语义完整、语法正确和有可复用价值的单位软件,包括程序代码、测试用例、设计文档、设计过程、需求分析文档和领域知识等。 广义上讲,构件可以是数据,也可以是被封装的对象类、软件构架、文档和测试用例等。 一个构件可以小到只有一个过程,也可以大到包含一个应用程序。 它可以包括函数、例程、对象、二进制对象、类库和数据包等。(参考MBA智库百科)
类创建者:创建新数据类型的程序员
客户端程序员:在其应用中使用数据类型的类消费者
替代原则:可以用一个导出类对象来完全替代一个基类对象,视为纯粹替代,是一种处理继承的理想方式。
弱类型:根据使用的情况随时改变的,由解释器解释
强类型:变量类型一经声明不能改变的,在编译时就进行检查
前期绑定:编译器将产生一个具体函数名字的调用,而运行时将这个调用解析到将要被执行的代码的绝对地址。
后期绑定:当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法存在,并对调用参数和返回值执行类型检查(不知晓方法的具体代码)。为了执行后期绑定,Java用在对象中的存储信息来计算方法体地址(待说明),替换绝对地址调用。这样,根据方法体地址,每个对象都可以具有不同的行为表现。当向一个对象发送消息时,该对象能知道对这条消息应该做什么。
向上转型:将导出类看成基类的过程(在继承图的典型布局方式中,通常基类在顶部,故称"向上")
中间件:一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。通过中间件,应用程序可以工作于多平台或 OS 环境。
所有变成语言都提供了抽象机制。汇编语言是对底层机器的轻微抽象,C、BASIC等是对汇编语言的抽象。问题的复杂性往往取决于你抽象的类型和质量。
程序是对象的集合,它们通过发送消息来告知彼此所要做的。这里的消息可理解是对某个对象的方法的调用请求。每个类最重要的区别于其他类的特性就是“可以发送什么样的消息给它”。
对象唯一标识(hashCode()方法获取),对应每个对象在内存中有唯一地址。不过对象可以存在于不同的机器和地址空间中,还可以被存储在硬盘上(序列化),不一定就在内存。
类描述了具有相同特性(数据元素)和行为(功能)的对象集合。程序通过定义类来适应问题,编程系统也接受新的类,像对待内置类型一样。
面向对象程序设计的挑战之一,就在问题空间的元素和解空间的对象之间创建一对一的映射。
程序本身将向用户提供服务,通过调用其他对象提供的服务来实现这一目的。把对象看成服务提供者,这样的好处是,提高对象的内聚性,实现高内聚。
把类的实现细节隐藏起来,完成访问控制。原因:让客户端程序员无法触及他们不应该触及的部分,快速忽略没必要看的;允许库设计者改变类内部的工作方式而不担心影响客户端程序员。
三个访问指定词设定边界:public、private、protected。当然还有默认的访问权限:包访问权限。
使用现有的类合成(如创建一个常被声明为private的成员对象)新的类,这种叫组合。若组合是动态发生的,称聚合。组合经常视为“has-a”关系,如“汽车拥有引擎”。
在建立新类时,应该首先考虑组合(达到复用效果),因为其更加简单灵活,而不是考虑继承(组合、继承的优缺点)。
当源类(即基类、超类或父类)发生变动时,被修改的“副本”(即导出类、继承类或子类)也会反映出这些变动。
应该要让基类和导出类产生差异。第一种是直接在导出类中添加新方法。但应该仔细考虑是否存在基类也需要这些额外方法的可能性。第二种是改变现有基类的方法的行为,即覆盖。
替代原则(父类与导出类之间的关系是is-a)是很好,但是在现实中,往往你需要在子类添加新方法(父类与导出类之间的关系是is-like-a),即扩展父类。
C++用virtual关键字实现后期绑定,而Java中动态绑定是默认行为,不用关键字即可实现多态。比如:
class Shape{
void doSomething(Shape shape){
shape.erase();
// ...
shape.draw();
}
// ...
void myTest(){
Circle circle = new Circle();
doSomething(circle);
}
}
例子中,编译器在编译doSomething()代码时,不知实参类型,故编译结果时调用基类的Shape的erase()和draw()版本,而不是Circle的那两个方法。至于后面运行时发生的,就是多态性的一种体现了,结果是调用Circle的那两个方法。
比如所有类的终极基类:Object。单根继承结构保证所有对象都具备某些功能,比如wait()、notify()等。也使垃圾回收器的实现变得容易得多。
新的对象类型持有对其他对象的引用,称为容器(也称集合,不过Java类库以不同的含义使用了“集合”)。不需要知道将多少对象置于容器中。
List用于存储序列;Map被称为关联数组,用来建立对象之间的关联;Set每种对象类型只持有一个;还有队列、树、堆栈等更多的构件。
不同容器提供不同类型的接口和外部行为,对某些操作具有不同效率(从底层数据结构可看出)。我们在一开始可以使用LinkedList构建程序,而在优化系统性能时改进ArrayList。
向下转型并非彻底危险,当转为错误的类型,就会得到异常的运行时错误。容器通过使用参数化类型(Java SE5添加,称泛型),编译器可以定制一个接纳和取出指定类型的容器,从而不需要向下转型及消除犯错误的可能。
使用对象,最关键之一在于它们的生成和销毁方式。C++将对象置于堆栈(即自动变量或限域变量)或静态存储区域来实现(在堆栈中创建存储空间和释放存储空间通常各需要一条汇编指令即可,分别对应栈顶指针向下移动和将栈顶指针向上移动),但这样缺少灵活性,需要编写代码时知道对象确切的数量、生命周期、类型,容易写死。
Java完全采用动态内存分配方式。在堆的内存池中动态创建对象。这种是运行时才知道需要多少对象、生命周期如何、具体类型是什么。为什么堆中创建要动态?因为堆中分配存储空间需要大量的时间,远大于在堆栈中创建的时间,故尽量在需要时才创建。
在堆栈上创建的对象,编译器可以确定对象存活时间,而在堆上的则不行。C++通过编程方式来确定何时销毁对象(可能因不能正确处理而导致内存泄漏)。Java有“垃圾回收器”机制(自动发现对象何时不再被使用,并继而销毁它),可避免暗藏的内存泄露问题。它和单根继承Object以及堆上创建对象,使得Java编程的过程比C++编程简单些。
异常处理将错误处理直接置于编程语言中,如try...catch。异常处理不是面向对象的特征,在其出现之前就存在了。
把问题切分成多个可独立运行的部分(任务),从而提高程序的相应能力,称并发。彼此独立运行的部分,称线程。线程只是一种为单一处理器分配执行时间的手段。多线程,让程序员不用担心机器上是多个处理器还是单个处理器。
共享资源是个问题。
单一服务器同时应对多个客户服务,可把数据“均衡”分布于数据表中。
减轻处理任务的负载:将负载分散给客户端机器处理;分散给在服务器端的其他机器(使用中间件)
客户端编程,意味着Web浏览器能用来执行任何它能完成的工作。包含:1. 插件;2. 脚本语言(源码嵌入HTML页面,页面显示时激活,缺点是代码暴露);3. Java(通过applet及Java web start来进行客户端编程;applet实现了客户端软件更新不产生错误,且无需重装)...