thinking in java笔记 1 对象导论
1.1 抽象过程
所有编程语言都提供抽象机制。人们能解决的问题的复杂性直接取决于抽象的类型和质量。
1 建立机器模型和实际待解问题的模型之间的关联:费力、难以编写
2 针对待解问题建模:针对特定问题是好方案、但局限性太强。
3 面向对象方式:
程序可以通过添加新类型的对象使自身适用于某个特定问题。当阅读描述解决方案的代码时,也是在阅读问题的表述。
面向对象的基本特性
1 万物皆为对象
2 程序是对象的集合,对象之间通过发送消息来通信。
3 每个对象中可包含其他对象,可构建复杂的体系。
4 每个对象都拥有其类型
5 某一特定类型的所有对象都可以接收同样的消息。
1.2 每个对象都有一个接口
可以创建某一类型的变量,然后操作这些变量。每个类的成员或元素都具有某种共性:每个账户都有结余金额;同时,每个成员都有其自身的状态:每个账户都有不同的结余金额。每一个对象都属于定义了特性和行为的某个特定的类。
因为类描述了具有相同特性和行为的对象集合,程序员通过定义类来适应问题,而不再被迫只能使用现有的用来表示机器中的存储单元的数据类型。可以根据需求,添加新的数据类型来扩展编程语言,编程系统接受新的类,并像对待内置类型一样照管它们和进行类型检查。
面向对象的挑战之一就是在问题空间的元素和解空间的对象之间创建一对一的映射。如何获取有用的对象?必须有某种方式产生对对象的请求,使对象完成各种任务,如完成一笔交易。每个对象都只能满足某些请求,这些请求由对象的interface所定义。
接口确定了对某一特定对象所能发出的请求,在程序中必须有满足这些请求的代码,这些代码与隐藏的数据一起构成了实现。
1.3 每个对象提供服务
将对象看为服务提供者:
目标就是创建能够提供理想服务来解决问题的一系列对象。
有助于提供对象的内聚性。每个对象都可以很好的完成一项任务,但并不试图做更多的事。
1.4 被隐藏的具体实现
程序开发人员分为类创建者(创建新数据类型)和客户端程序员(使用新数据类型)。
类创建者的目标是构建类,这些类只向客户端程序员暴露必须的部分,而隐藏其他部分。好处在于隐藏的部分客户端无法访问,创建者可以任意修改隐藏的部分。
1.5 复用具体实现
先组合,再继承。避免过分复杂的设计。
1.6 继承
可通过继承来构建一个类型层次结构,以此来表示待求解的某种类型的问题。
当继承现有类型时,也就创造了新的类型,这个新的类型不仅包括现有类型的所有成员,而且更重要的是它复制了父类的接口,也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。由于通过发送给类的消息的类型可知类的类型,也意味着导出类与基类具有相同的类型。
由于基类与导出类具有相同的基础接口,所以伴随此接口的必定有某些具体实现,也就是说当对象接受到特定消息时,必须有某些代码去执行。
有两种方法可以使基类与导出类产生差异:
1 在导出类中添加新方法
2 overriding 改变基类方法
继承包括 纯粹替代(is-a)和非纯粹替代(is-like-a)
1.7 伴随多态的可互换对象
在处理类型的层次结构时,经常想把一个对象不当做它所属的特定类型来对待,而是将其当做其基类的对象来对待,这使得人们可以编写出不依赖于特定类型的代码。
通过导出新的子类型而轻松扩展设计的能力是对改动进行封装的基本方式之一,可改善设计,降低软件维护代价。
直接调用泛化基类的方法时,泛化基类必须去调用对应的导出类型的方法,但如何知道调用哪个导出类型呢?(即实现多态)
通过后期绑定。当向对象发送消息时,被调用的代码直到运行时才能确定,编译器确保被调用方法的存在,并对调用参数和返回值进行类型检查,但是不知道将被执行的确切代码。
1.8 单根继承结构
所有类都继承自Object类。
单根继承结构保证所有对象都具备某些功能。因此,在你的系统中你可以在每个对象上执行某些基本操作,所有对象都可以很容易的在堆上创建,而参数传递也得到了极大的简化。 单根继承结构使垃圾回收器的实行变得容易的多。由于所有对象都保证具有类型信息,因此不会因无法确定对象的类型而陷入僵局,对于系统级的操作(如异常处理)显得尤其重要,更为灵活。
1.9 容器
Java中有满足不同需要的各种类型的容器,如List(用于存储序列),Map(也被称为关联数组,用于建立对象之间的关联),Set(每种对象类型只持有一个),以及诸如队列、树、堆栈等更多的构件。
在Java SE5之前,容器存储的对象都为Object类型,因此可以存储任何东西,容易复用。但此时的容器存入时需向上转型为Object,造成类型信息丢失,取出时必须对其进行手动的向下转型,向下转型有可能会出现运行时错误,是不安全行为。
泛型的出现解决了这一问题,如 ArrayList<Shape> shapes=new ArrayList<Shape>(); 此处定制了一个只接纳和取出shape对象的容器。泛型可以避免转型错误和转型消耗的时间。
1.10 对象的创建和生命期
Java完全采用动态内存分配方式。每当想要创建新对象时,就要使用new 关键字来构建此对象的动态实例。
Java的垃圾回收器被设计用来处理内存释放问题。垃圾回收器知道对象何时不再被使用,并自动释放对象占用的内存。这一点同所有对象都是继承自单根基类Object以及只能以一种方式创建对象(在堆上创建)这两个特性结合起来,使Java编程容易的多。
1.11 异常处理
Java内置了异常处理,且强制必须使用。它是唯一可接受的错误报告方式,如果没有编写正确的处理异常的代码,就会得到一条编译时的出错信息。
1.12 并发编程
有时中断对于处理时间性比较强的任务是必需的,但对于大量的其他问题,我们只是想把问题切分成多个可独立运行的部分,从而提高程序的响应能力。这些彼此独立运行的部分称为线程。
一个隐患为:共享资源。因此,整个过程是:某个任务锁定其资源,完成其任务,然后释放资源锁,使其他任务可以使用该项资源。