[Java编程思想-学习笔记]第1章 对象导论
1.1 抽象过程
Java是一门面向对象的语言,它的一个优点在于只针对待解问题抽象,而不用为具体的计算机结构而烦心,这使得Java有完美的移植性,也即Java的口号"Write Once, Run Anywhere"。
所谓的抽象过程,可以理解为对待解问题建模。比如待解问题是一个人,那么我们可以对人进行建模,它的类型是人,有属性姓名、性别、年龄,还有行为吃饭、走路。Java能直接完全据此建模编码,而无需考虑具体的计算机结构。所以当我们阅读Java程序时,正如书上说的"当你在阅读描述解决方案的代码的同时,也是在阅读问题的表述"。
1.2 对象的属性
正如我们所观察到的,人有属性姓名和年龄,圆有属性半径,三角形有属性边长和角度,每个对象都有一定的属性,也可以称属性是对象的成员。
1.3 每个对象都提供服务
每个对象都提供服务也是面向对象的一个重要的思想。
就像在人类世界里,造房子是为了住宿,造车子是为了出行,造学校是为了教育,造医院是为了医治。同样的,在Java中造对象当然是为了给用户使用。如果所造的对象没有一点用处,不能提供任何有用的服务,那简直成了垃圾对象。
既然每个对象都能提供服务,就意味着对象能做一些事,有一些公共方法可以被其他对象使用,这些公共方法也称为接口。
1.4 每个对象都有一个接口
面向对象有一个最重要的思想——物以类聚,各从其类。大千世界,无论何物,它都被视为一个实例化的对象,并且任何一个实例化的对象必定是按照一个模板创建出来的,其中此模板就是类。读过生物的应该都了解任何生物都可以根据"界、门、纲、目、科、属、种"进行分类,如果是非生物的,比如病毒、石头、沙子等,可当我们叫出它们的名字时,我们也找到了其所属的类。
科普一下接口的定义:简单来说,接口指的是“我能做什么”。(不妨打开JAVA的API,看看java.lang包,里面的接口如Appendable,Cloneable,Runnable,后缀都是-able,这样的命名也体现了接口的含义)
问题来了,为什么要用接口?为什么每个对象都有一个接口?我们不妨看看电视机这个实例化的对象,我们按打开按钮时,它就收到"打开"的请求,然后内部就做了一些工作,最后屏幕就亮了,我们按下一个频道时,它就收到"下一个频道"的请求,然后内部就做了一些工作,最后显示下一个频道。其实每个对象都应有相同的工作机制,比如人吃饭,人吃一口饭,内部也就收到"吃"的请求,然后就是一系列的消化的工作,最后会化作每个细胞工作需要的能量。我们对这种工作机制抽象,因而有了接口和实现的概念。接口,就像暴露在电视机外面的按钮一样,有打开,上/下一个频道,音量+/-等功能按钮;实现,就像隐藏在电视机里面复杂的内部工作一样,它最好是隐藏起来的。之所以说每个对象都有一个接口,就是避免把类设计成黑盒子,如果电视机一个接口也没有,那么我们即使用遥控器也没能操作它,这样的电视机有什么用处?因此这就告诫每个程序员,设计类的同时必须至少定义一个公共方法。
1.5 被隐藏的具体实现
为什么要把具体实现隐藏起来?除了 1.4 节所述原因,还有另一个重要的原因。要知道这编程世界有两种程序员,一者曰类创建者(那些创建新数据类型的程序员),二者曰客户端程序员(那些在其应用中使用数据类型的类消费者)。最普遍的,假设称Java类库的创建者为A1(即类创建者),称我们这些使用Java类库的程序员为A2(即客户端程序员)。A1与A2形成一种关系,A1负责构建类,而A2使用A1提供的类来做开发。假设类创建者开发了一个计算组合数的类Combination,数学上组合数的公式为C(n,m)=m!/n!(m-n)!,我们可以定义两个方法,一个是计算阶乘,另一个是计算组合数,我们不希望计算阶乘的方法成为接口暴露出去,因为一旦暴露了,客户端程序员就可以随意设置参数,修改内部实现,因此应当把这类具体实现隐藏起来,这样才能避免被毁坏,减少程序的bug,此外,这样做对客户端程序员而言也是一种服务,因为这样他们就知道哪些方法是可用的,哪些方法是不可用的,还有一个原因是,当我需要修改隐藏的实现时,不会影响到客户端程序员,比如我原来是使用循环来实现阶乘的计算,但后来我发现用递归更加好,我这么一改,甚至连方法名都改了,但是这个类的接口依然没变,所以没影响到客户端程序员。
其实不仅要隐藏具体实现,还应当隐藏对象的属性。这些属性和具体实现的隐藏在面向对象中被称为封装。封装的意义在于保护了,比如人,他有属性年龄,我们都知道年龄必须是非负数的,如果没有封装起来,一些调皮的程序员就可以随意篡改了,比如改成 -1 岁,年龄哪能是负数?所以为了防止篡改,保护对象的属性,就引入了封装。
1.6 复用具体实现
复用具体实现是Java的一大特色了。这里涉及了类之间的关系:聚合、组合、继承、关联、依赖。
简单来讲,聚合就是拥有关系,但是两者生命周期不一致,比如人拥有一台电脑就是聚合关系,其中电脑的寿命到了,但人的寿命还没到,人的寿命到了,但电脑的寿命还没到;
组合也是拥有关系,更是一种强聚合关系,两者的生命周期是一致的。比如人和自己的大脑,两者谁也不能离开谁;
继承不用多说了,比如苹果继承自水果,苹果是水果;
关联也是拥有关系,不同的是,关联是一对多的关系,比如一个订单只能有一个客户,而一个客户拥有多个订单;
依赖就是使用关系,比如一个人要过河,他就需要使用一下船只,在代码里体现在一个类的方法定义了被依赖类的局部变量,或者被依赖类作为此类方法的参数。
1.7 继承
继承是复用代码的一种方式,它是指在现有的一个类的基础上创建一个新的类,被继承的类称为基类(或父类、超类),继承出的类成为导出类(或子类、次类)。
继承有三种情形,1.导出类什么都没做,因此导出类与基类完全一样;2.导出类覆盖(修改)了基类的方法,即导出类纯替代了基类;3.导出类添加了新的方法,还可能覆盖了基类的方法,此时导出类扩展了基类,实际上我们在继承时往往都是扩展基类。
在继承上Java与C++最大的不同就是单根继承了,每个类都只能继承自一个类,并且,Java中所有的类都直接或间接地继承自根类Object,如下图所示

1.8 伴随多态的可互换对象
如 1.7 节所示,我们可以说直角三角形是一个三角形,等边三角形是一个三角形,但三角形不一定是直角三角形或等边三角形。假设我们已经设计了三角形的继承体系,这时我们再设计一个操作三角形的类,类中有一个方法用来填充三角形,但已知有三种三角形,即直角三角形、等腰三角形以及等边三角形,难道要分别为这三种三角形重载三种填充方法吗?不必,多态使得只要在参数上接受三角形这种泛化的类型即可,也就是说,无论是哪种三角形,在多态上都视为三角形,因此能被方法的参数所接受,故也都能被填充。比如下面的程序:
// 不使用多态
void fill(直角 e) { print("填充直角三角形"); }
void fill(等腰 e) { print("填充等腰三角形"); }
void fill(等边 e) { print("填充等边三角形"); }
// 使用多态
void fill(三角形 e) { print("填充" + e); }
可见,因多态机制,代码更加简洁。
到此,补充一句面试爱问的问题:封装、继承和多态是面向对象的三个特征。
1.9 单根继承结构
如 1.7 节所示,Java中所有的类最终都继承自单一的基类,就是Object。这样的单根继承结构有三个优点:
- 所有对象都具有一个共用接口,这样它们归根到底都是相同的基本类型,在设计时还可以利用适配器模式解决接口不兼容问题;
- 保证所有对象都具备某些功能,比如都有toString( )、equal( )方法;
- 使垃圾回收器的实现变得更加容易,因为能保证每个对象具有其类型信息。
1.10 容器
我们都知道在声明数组时必须要指定其大小,而一指定大小就再也不能改了,那问题来了,如果数组的大小仍然不够那怎么办?也只能重新再定义一个数组了,这样子就很不方便了。为解决这个问题Java提供了容器,容器能根据自己所需的元素个数动态地调整容器的大小。容器有Set,Map,List以及栈、队列、树等,其中面试最爱问的就是ArrayList了。
1.11 对象的创建和生命周期
在Java中,创建对象只要使用new关键字即可,然后对象就被创建在堆中,如果对象是创建在堆栈上,编译器就能确定它的生命周期,还可以销毁它,但对象是存在于堆中,编译器就无法确定对象的存活时间了。为了销毁对象,释放内存,Java提供了垃圾回收机制,程序员就不再需要手动销毁对象了,这对程序的编写的确是方便了许多。
当然Java这样做也是有弊端的,因为对象是存在于堆的,因此对对象的创建和操作会慢一些,此外把销毁对象的工作交给垃圾回收器,这样子有点不放心,如果程序退出了,但垃圾回收器还没有销毁对象呢,因此Java程序占用内存高就闻名世界了。
1.12 异常处理:处理错误
举个例子,我们设计一个简单除法的方法divide
int divide(int x, int y) { return x / y; }
这时如果对 y 赋值为0,程序就运行异常,然后二话不说直接退出,很明显程序体验太差,其实这情况还不算太差,如果是为银行、军事、航空设计程序,但没有处理好异常,那样子该有多危险。所以为了确保程序的健壮性,必须要能处理好异常。
1.13 并发编程
许多程序设计问题都要求,程序能够停下正在做的工作,转而解决其他问题。有的程序还要求能够同时做多件事情。比如下载,我们希望同时下载多个资源,支持断点续传,可以暂停下载;比如QQ在线状态,可以一边聊天一边查看好友的状态。对这些问题,只能使用多线程来解决。
[Java编程思想-学习笔记]第1章 对象导论的更多相关文章
- [Java编程思想-学习笔记]第3章 操作符
3.1 更简单的打印语句 学习编程语言的通许遇到的第一个程序无非打印"Hello, world"了,然而在Java中要写成 System.out.println("He ...
- [Java编程思想-学习笔记]第2章 一切都是对象
2.1 创建新的数据类型:类 通过第一章掌握了面向对象的理论后,我们知道每个对象必定属于一个类型,那么Java如何创建新的数据类型?如下程序所示: class Circle { // 属性 // 方 ...
- [Java编程思想-学习笔记]第4章 控制执行流程
4.1 return 关键字return有两方面的用途:一方面指定一个方法结束时返回一个值:一方面强行在return位置结束整个方法,如下所示: char test(int score) { if ...
- Java编程思想学习笔记——一切都是对象
前言 Java是基于C++的,但Java是一种更加纯粹的面向对象程序设计语言. C++和Java都是混合/杂合型语言.杂合型语言允许多种编程风格. 用引用操纵对象 每种编程语言都有自己操纵内存中元素的 ...
- JAVA编程思想读书笔记(四)--对象的克隆
接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...
- Java编程思想 学习笔记1
一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...
- Java编程思想学习(五)----第5章:初始化与清理
随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一. C++引入了构造嚣(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法.Java中也采用了构造器,并 ...
- Java编程思想 学习笔记5
五.初始化与清理 1.用构造器确保初始化 在Java中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.创建对象时,如果其类具有构造器,Java就会在用户有能力操作对象之前自动调用相应的构造 ...
- Java编程思想学习笔记_1(Java内存和垃圾回收)
1.Java中对象的存储数据的地方: 共有五个不同的地方可以存储数据. 1)寄存器.最快,因为位于处理器的内部,寄存器按需求分配,不能直接控制. 2)堆栈.位于通用RAM,通过堆栈指针可以从处理器那里 ...
随机推荐
- js操作label,给label赋值,和取label的值
取值:var Label_text=document.getElementById('test_label').innerHTML; 赋值:document.getElementById('test_ ...
- Java学习笔记——回调函数
转载:http://wangyang0311.iteye.com/blog/368031 一般来说分为以下几步: 声明回调函数的统一接口interface A,包含方法callback(); 在调用类 ...
- 如何利用Oracle外部表导入文本文件的数据
同事最近在忙数据一致性比对工作,需要对不同文本文件中的数据进行比对,有的文件较大,记录较多,如果用普通的文本编辑器打开的话,很显然,会很卡,甚至打不开. 基于此,可将该文本文件的数据导入到数据库中,在 ...
- 初探和实现websocket心跳重连
心跳重连缘由 在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时性关闭,这时候websocket的连接已经断开, 而浏览器不会执行websocket 的 onclos ...
- java基础--java.util.Date类型小结
首先先来了解一下Date数据类型: . Date类型通常要和另一个 java.text.SimpleDateFormat类联合使用. 把long-->Date: public Date(long ...
- Oracle11g中数据的倒库和入库操作以及高版本数据导入低版本数据可能引发的问题
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在10g之前,传统的导出和导入分别使用EXP工具和IMP工具 ...
- 解决ASP.NET Core Mvc文件上传限制问题
一.简介 在ASP.NET Core MVC中,文件上传的最大上传文件默认为20MB,如果我们想上传一些比较大的文件,就不知道怎么去设置了,没有了Web.Config我们应该如何下手呢? 二.设置上传 ...
- 数三角形 bzoj 1201
数三角形(1s 128MB)triangle [题目描述] 小苏看到一个这样的等边三角形:该等边三角形每边的长度为n且被分成n等份,于是每条边就有n-1个等分点.而整个三角形被连接两个不同边的等分点且 ...
- C++11之std::function和std::bind
std::function是可调用对象的包装器,它最重要的功能是实现延时调用: #include "stdafx.h" #include<iostream>// std ...
- big-endian和little-endian
1.故事的起源 "endian"这个词出自<格列佛游记>.小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开 ...