一、抽象过程
1.万物皆为对象:理论上来说,我们可以抽取待解决问题中任何一个概念化的构件,将其描述成为程序中的一个对象。
2.程序是对象的集合,它们通过发送消息来告知彼此需要做的事:通俗来讲,程序是一系列对象的集合体,程序之间的通信可以细分到对象与对象之间的通信,要想进行通信就需要发送消息。从程序的角度来说,消息传递这个过程可以理解为一个方法的调用与执行。
3.每个对象都可以由其它对象组成:换句话说,对象之间可以进行组合,形成新的具有具体意义的对象。
4.每个对象拥有其自己的类型:类型用来区分不同对象的特征,比如正方形有四条边,三角形有三条边,边的条数就可以用来区分二者。
5.某一特定类型的所有对象,都可以接收同样的消息:也就是说,具有相同类型的一系列对象,它们具有的行为是相同的,因此它们可以接收/处理相同的消息。
对象具有行为、状态和标识,每一个对象都可以拥有内部数据和方法,数据用来表示对象的状态,方法用来产生特定的行为,每个对象有唯一的标识与其它对象区分。拥有相同类型的对象的集合称作类,也就是说我们创建的每一个对象,都来自一个类。
二、每个对象都有一个接口
对象之间进行消息传递时是通过接口来完成的,一个对象的接口暴露给另一个对象,接口对应内部的一个具体实现,具体实现表示特定的方法行为。
三、每个对象都提供服务
我们拆分、抽取的每一个对象,都是具有实际业务意义的,它们都应该能够传递具体的消息,从而提供特定的服务。
四、被隐藏的具体实现
很多时候,我们将开发者分为两种,类创建者和客户端开发人员,所谓类创建者,可以理解为对象集合的构建者,客户端开发人员负责使用他们所创建的对象。有些时候,为了避免客户端开发者恶意修改类的功能,或者为了类在不断升级的过程中,能够更好地实现向下兼容,我们需要对客户端开发人员屏蔽一些他们用不到的且很关键的代码。这个屏蔽的过程叫做访问控制。
Java中提供了三个级别的访问控制,分别为public、protected、private。public顾名思义就是所有人可见。private就是只有类的创建者可见。protected介于二者之间,在由基类派生出的派生类中,可以访问派生类中被protected修饰的域,而不能访问private域,其它与private相同。具体的访问控制后文继续学习。
五、复用具体实现
有些时候我们需要使用一个现有的类完成特定的功能,但是又不能完成全部功能,那么我们就可以创建一个新的类,在这个类中引入先前的类的对象,并将其声明为private域,这样的话我们就可以使用这个对象的方法来完成一部分功能,然后在新类中创建新的属性和方法,并且在外人看来它就是一个新的类。这种“has-a”的关系我们称为组合。
六、继承
当我们创建一个类时,如果另一个新类与这个类功能相似,我们仍然需要创建这个新类。解决这个问题的办法就是继承。继承虽然也是一个新类,但是这个类是由基类(俗称父类)衍生的导出类(俗称子类)。子类拥有父类所有非private的对象、属性、接口,此外可以根据不同的需要增加不同的功能。父类可以有很多个子类,它包含了子类的所有公共部分。如“几何形”是父类,每一个几何形都具有尺寸、颜色、位置等,同时每一个几何形都可以被绘制、擦除和移动。在此基础上可以导出它的子类“三角形”、“平行四边形”等,他们拥有父类的属性、方法之外还有自己独特的属性,例如有的形状可以被翻转等。
子类不光继承了父类的属性,同时也继承了父类的方法,也就是说所有发给父类的消息,都可以发给子类。子类对接口的实现方法可以不改变,即访问子类的接口实际是与访问父类相同,当然也可以自己“覆盖”父类接口的方法,也就是说我和父类使用相同的接口,但是我们做不同的事情。同时如前边所说,子类也可以自己新增方法来满足自己的需求。前者不改变或者覆盖接口的方法,这种我们称作是“is-a”的关系,因为子类与父类本质的类型没有发生变化。而后边这种我们称作是“is-like-a”,因为在子类中增加了新的方法,所以这种相同的关系并不完全。
七、伴随多态的可互换对象
我们说子类继承父类,同时继承了父类的方法,也就是说发给父类的消息同时能够发给子类。那么当我们把子类对象看成泛化的基类对象时,如果有个方法是让泛化的父类操作自己,那么编译器在编译时不知道该执行哪段代码的。一个非面向对象程序的函数调用是前期绑定,函数要执行的代码在程序运行之前就已经确定了,然而在面向对象中,直到程序执行我们才知道哪段代码被执行了。所以为了解决消息执行哪段代码的问题,Java使用了后期绑定的概念,使用一小段特殊的代码来代替非面向对象中所说的绝对地址调用,这段代码使用在对象中存储的信息来计算方法的地址。比如有个父类Shape和子类Circle、子类Triangle,父类中有如下方法
1 | void doSomething(Shape shape){ |
这个方法可以与任意Shape类型的对象交互,如果程序中有它的子类调用了该方法
1 | Circle circle = new Circle(); |
八、单根继承结构
在Java语言中,所有的类都是Object类的子类,拥有着Object类的基本方法。这种单根继承结构有很大的好处,比如在垃圾回收中可以避免由于不知道对象的类型而无处下手,因为他们都可以使用Object类的方法,并且所有对象都可以很容易的在堆上创建。
九、容器
有时候我们并不知道处理一个问题需要多少个对象,或者他们需要存活多久,那么我们就不知道该怎么样存储这些对象。Java语言中创建了一种对象类型,叫做容器(也叫集合)。这种新的对象类型内部有对其他对象的引用,当你需要的时候你可以很容易的扩充容器的空间来容纳对象。Java中提供了多种容器类型,如List(用于存储序列)、Map(也被称为关联数组,用来建立对象的关联)、Set(每种对象类型只持有一个)。因为容器中存储了其他对象的引用,所以根据单根继承结构,容器中的对象类型都是Obejct类型,这样很方便其他对象类型进行转型。但是从Object类型转到其它特定类型(称作向下转型)很容易发生错误,所以Java SE5之后引入了泛型的概念,参数传递使用一对<>,<>内部可以传递任意类型的对象,这便解决了向下转型带来的安全隐患。
十、对象的创建和生命周期
对象的创建主要有两种,一种是在编程时由程序员控制,将对象置于栈中或者是静态区域,这种的好处是知道对象的大小、生命周期。同时也限制了对象的灵活性。另一种是通过new在内存堆中动态的创建对象,这种方式的好处是灵活,需要的时候直接在内存中创建即可,实现了存储空间的动态管理。Java中完全采用了动态内存的分配方式。
对于生命周期,栈上的生命周期,编译器可以知道它什么时候销毁,并自动回收。而在堆上创建的对象,必须由程序员自己指定回收时间,如果没有指定则会造成内存泄漏。Java中提供了垃圾回收机制,可以自动的回收在堆上创建的对象。
十一、异常处理:处理错误
Java内置了异常处理机制,相当于一条与正确执行并行的路线,当程序发生异常时会执行异常的代码。同时,允许程序在异常中进行处理并返回到正确的结果中去。
十二、并发编程
Java与其他语言一样,提供多线程的并发编程方式,提高程序运行效率。
十三、Java与Internet
Java不仅可以编写客户端程序,还可以编写网络Web应用程序。