java 编程思想的学习笔记 - 第一章

开篇: 本系列文章是用来记录 java编程思想的 学习笔记,以及记录自己的理解 ,主要目的是促进自己对java 的进一步了解

文章中如有描述或者理解有问题的部分 请博友告知,以便共同交流进步

第一章 对象引论

抽象过程

所有的变成语言都提供抽象机制。可以认为,你所能够解决问题的复杂性直接取决于抽象的类型和质量。
上面所说的抽象类型 这里举例说明下

汇编语言是对底层机器的抽象

底层机器   --> 汇编语言  

接着出现的命令语言  FORTRAN、BASIC、C 等  是对汇编语言的抽象,这些语言在汇编语言之上有了大幅的改进,但是它们所作的主要抽象仍要求你在解决问题时要基于计算机的结构,而不是基于你试图要解决的问题的结构来考量。

汇编语言 --> FORTRAN、BASIC、C 等  

j ava等面向对象语言的抽象是 将对象-->抽象为java对象 

每个对象都拥有状态、行为、和标识。这意味着每个对象都可以拥有内部数据和方法,并且每个对象都可以唯一的和其他对象区分开,具体来说就是每个对象在内存中都有唯一的地址。

当你正是如开发或理解一个程序设计时,最好的方法之一就是将对象想象为“服务提供者。你的程序本身将向用户提供服务,它将通过调用其它对象提供的服务来实现这一目的。

将对象看作是服务提供者还有一个附加的好处:它有助于提高对象的内聚性(cohesiveness)。//ps:有点和设计模式接轨的意思

被隐藏的具体实现

将程序开发人员按照角色分为类创建者(可理解为后端) 和客户端程序员(可理解前端或者接口调用方)是大有裨益的。

类创建者的目标是构建类,该类只向客户端程序员暴露必需的部分,而隐藏其它所有部分。为什么要这样呢?因为如果加以隐藏,那么客户端程序员将不能够访问它,这意味着类创建者可以任意修改被隐藏的部分,而不用担心对其他任何人造成影响。被隐藏的部分通常代表对象内部脆弱的部分,它们很容易被粗心的或不知内情的客户端程序员所毁坏,因此将实现隐藏起来可以减少程序的Bug。

如果没有任何访问控制,所有东西都将赤裸裸暴露在外面.

访问控制的第一个存在原因就是让客户端程序员无法触及他们不应该触及的部分

访问控制的第二个存在原因就是允许库设计者可以改变类内部的工作方式而不用担心是否会影响到客户端程序员。(是指调用方式吧)

java里的这种访问控制是通过三个关键词来控制的: public 、private 、protected

public 表示紧随其后的元素对任何人都是可用的。

private 这个关键字表示除类型创建者和该类型的内部方法之外的任何人都不能访问的元素。private 就像你与客户端程序员之间的一堵砖墙,如果有人试图访问 private 成员,就会在编译时刻得到错误信息。

protected和private差别仅在于继承类(Inheriting class)可以访问 protected成员,但是不能访问 private 成员。(子类可以访问protected)

Java 还有一种缺省(default)的访问权限,包内可访问。

复用具体实现

最简单的复用某个类的方式就是直接使用该类的一个对象,此外你也可以将该类的一个对象置于某个新的类中。我们称其为“创建一个成员对象”。 --聚合关系   组合关系是拥有关系,比如 car 类引用轮胎,引擎,座位等对象 。而聚合只是是引用。

实际上,在建立新类时,你应该首先考虑组合,因为它更加简单而灵活。如果你采用这种方式,你的设计会变得更加清晰。一旦有了一些经验之后,你便能够看透必须使用继承的场合。

继承:复用接口

接口是用来解决在创建了一个类之后,即使另一个新类与其具有相似的功能,你还是得重新创建一个新类。如果我们能够以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新类那就要好得多了。

一个基类包含其所有导出类共享的特性和行为。你可以创建一个基类来表示系统中某些对象的核心概念,从基类中导出其它的类,来表示此核心可以被实现的各种不同方式。


例子是经典的在计算机辅助设计系统或游戏仿真系统中可能被泳道的几何形(shape)的例子。基类是 shape,每一个 shape 都具有尺寸、颜色、位置等,同时每一个 shape 都可以被绘制、擦除、移动和着色等。在此基础上,可以导出(继承出)具体的几何形状——圆形、正方形、三角形等——每一种都具有额外的特性和行为,例如某些形状可以被翻转。某些行为可能并不相同,例如面积计算。类型层次结构同时体现了几何形状之间的相似性和相异性。

java 编程思想的学习笔记 - 第一章




在 Java中,动态绑定是缺省行为,你不需要添加额外的关键字来实现多态(polymorphism)。


抽象基类和接口

Interface(接口)这个关键字比抽象类的概念更进了一步,它压根不允许有任何方法定义。接口是一个非常方便而通用的工具,因为它提供了接口与实现的完美分离。此外,只要你愿意,你就可以将多个接口组合到一起,与之相对照的,你要继承多个一般类或抽象类却是不可能的。



对象的创建、使用和生命周期

对象最重要的要素之一便是它们的生成和销毁。

C的效率是重要议题,所以为了追求效率把控制选择权交给了程序员,但是失去了灵活性,过于受限。

Java 提供了被称为“垃圾回收器(garbage collector)”的机制,它可以自动发现对象何时不再被使用,并继而销毁它。垃圾回收器非常有用,因为它减少了你必须考虑的议题和你必须编写的代码。更重要的是,垃圾回收器提供了更高层的保障,可以避免暗藏的内存泄漏问题

集合(collection)与迭代器(iterator

有两个原因使得你还是需要对容器有所选择。第一,不同容器提供了不同类型的接口和外部行。堆栈与队列就具备不同的接口和行为,也不同于集合(set)和列表。其中某种容器提供的问题解决方案可能比其它容器要灵活的多。第二,不同的容器对于某些操作具有不同的效率。

最好的例子就是两种 List 的比较:ArrayList 和 LinkedList。它们都是具有相同接口和外部行为的简单的序列,但是它们对某些操作所花费的代价却有天壤之别。在 ArrayList 中随机访问元素是一个花费固定时间的操作,但是,对 LinkedList 来说,随即选取元素需要在列表中移动,其代价是高昂的,访问越靠近表尾的元素,花费的时间越长。

另一方面,如果你想在序列中间插入一个元素,LinkedList 的开销却比 ArrayList 要小。 

单根继承结构

在单根继承结构中的所有对象都具有一个共用接口,所以它们归根到底都是相同的基本类型。Object

向下转型(downcasting)与模板/泛型(template/generic

向下转型(Object-->int)和运行时刻的检查需要额外的程序运行时间和程序员心血。那么创建知道自己所保存对象的类型的容器,从而消除向下转型的需求和犯错误的可能不是更有意义吗?其解决方案被称为参数化类型(parameterized type)机制。参数化类型就是编译器可以自动定制作用于特定类型之上的类。例如,通过使用参数化类型,编译器可以定制一个只接纳和取出 Shape对象的容器。 另可通过泛型定义

确保正确清除

例如,假设你正在为某个机场设计空中交通管理系统。一开始问题似乎很简单:创建一个容器来保存所有的飞机,然后为每一架进入控制交通控制区域的飞机创建一个新的飞机对象,并将其置于容器中。对于清除工作,只需在飞机离开此区域时删除相关的飞机对象即可。

但是,可能还另有某个系统记录着有关飞机的数据,也许这些数据不需要像主要的控制功能那样立刻受到人们的注意。例如,它可能记录着所有飞离飞机场的小型飞机的飞行计划。因此你需要有第二个容器用来存放小型飞机,无论何时,只要创建的是小型飞机对象,那么它同时也应该置入第二个容器内。然后某个后台进程在空闲时间对第二个容器内的对象执行操作。

Java 的垃圾回收器被设计用来处理内存释放问题(尽管它不包括清除对象的其他方面)。垃圾回收器“知道”对象何时不再被使用,并自动释放该对象的内存。这与所有对象都是继承自单根基类 Object,以及你只能以一种方式创建对象——在堆上创建这两个特性一起,使得用 Java 编程的过程较之用 C++编程要简单得多,你要做的决策和要克服的障碍都要少得多。

垃圾回收与效率和灵活性

java垃圾回收机制在提供编程方便的同时是消耗了内存和运行效率座位代价的.

异常处理:处理错误

Java 的异常处理在众多的编程语言中格外引人注目,因为 Java 一开始就内置了异常处理,而且强制你必须使用它。如果你没有编写正确的处理异常的代码,那么你就会得到一条编译时刻的出错消息。这种得到确保的一致性有时会使得错误处理非常容易。

并发(concurrency

通常,线程只是一种为单一处理器分配执行时间的手段。但是如果操作系统支持多处理器,那么每个线程都可以被指派给不同的处理器,并且它们是在真正地并行执行。在语言级别上多线程所带来的便利之一便是程序员不用再操心机器上有多个处理器还是只有一个处理器。由于程序被逻辑化分为线程,所以如果机器拥有多个处理器,那么程序将在不需要特殊调整的情况下执行得更快。

所有这些都使得线程看起来相当简单,但是有一个隐患:共享资源。如果有超过一个的并行线程都要访问同一项资源,那么就会出问题。例如,两个进程不能同时向一台打印机发送信息。为了解决这个问题,可以共享的资源,例如打印机,必须在被使用期间锁定。因此,整个过程是;某个线程锁定某项资源,完成其任务,然后释放资源锁,使其它线程可以使用这项资源。

Java 的线程机制是内置于其中的,它使此复杂课题变得简单得多了。线程机制被对象层次所支持,因此线程的执行可以用对象来表示。Java 同时也提供了限制性资源锁定功能,它可以锁定任何对象所占用的内存(毕竟这也算是某种共享资源),使得同一时刻只能有一个线程在使用它。这是通过 synchronized 关键字来实现的。其它类型的资源必须由程序员显式地锁定,通常是通过创建一个表示锁的对象,所有线程在访问资源之前先检查这个对象。(没懂这块)