前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Java编程思想》第一章:对象导论 原

《Java编程思想》第一章:对象导论 原

作者头像
云飞扬
发布2019-03-13 10:22:42
4590
发布2019-03-13 10:22:42
举报
文章被收录于专栏:星汉技术星汉技术星汉技术

    本人的笔记风格是,将书中的重要知识点摘抄出来,如果是特别转弯的话,本人会用自己的理解进行说明。从现在开始讲读书笔记一篇一篇的抛出来,供大家参阅学习讨论,如果错误的地方,请批评指正。首先是《Java编程思想》。

第一章:对象导论

    “我们之所以将自然界分解,组成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来……除非赞成这个协定中规定的有关语言信息的组织和分类,否则我们根本无法交谈”

——Benjamin Lee Whorf(1897~1941)

    (本人非常喜欢这段话,就摘了出来,完美的诠释了语言对于人类的意义于作用。)

    计算机革命起源于机器,因此,编程语言的产生也始于对机器的模仿。

    本章将介绍包括开发方法概述在内的OOP(Object-oriented Programming)的基本概念。

1、抽象过程

    所有编程语言都提供抽象机制。(个人认为,抽象很重要,这是一个人进入编程行当的基础,如果没有想象和联想的能力,建议你还是不要从事编程行业了,不然会很吃力,或许转个行业对你来说会很好!)

    程序员必须建立起在机器模型和实际待解决问题的模型之间的关联。建立这种映射是费力的,而且这不属于编程语言所固有的功能,这使得程序难以编写,并且维护代价高昂,同时也产生了作为副产物的整个“编程方法”行业。(这一句话就说明了抽象的重要性。)

    另一种对机器建模的方式就是只针对待解决问题建模。(简化工作的开始)

    面向对象方式通过向程序员提供表示问题空间中的元素的工具而更近了一步。我们将问题空间中的元素及其在解空间中的表示称为“对象”。(如果没有想象和联想,这一句话很难理解。)

    Alan Kay曾总结了第一个成功的面向对象语言——Smalltalk的五个基本特性:

    1.万物皆为对象。

    2.程序是对象的集合,它们通过发送消息来告知彼此索要做的。

    3.每个对象都有自己的由其他对象所构成的存储。

    4.每个对象都拥有其类型。

    5.某一特定类型的所有对象都可以接收同样的消息。

    此语言也是Java所基于的语言之一。

    Booch对对象提出了一个更加简洁的描述:对象具有状态、行为和标识。

    对象的状态:内部提供的数据。

    对象的行为:对象内部的方法。

    对象的标识:对象在内存中有一个唯一的内存地址。用于区分不同的对象。

    (个人理解,其实对象就是一个事物在程序中的一个缩影,引用就相当于给对象起个名字。名字可以随时更改,但是对象本身性质不会改变。可以先将一个对象局限性的理解为一个人,彻底理解之后,再扩大的想象,将它类比为所有你能类比的东西。)

2、每个对象都是一个接口

    所有的对象都是唯一的,但同时也是具有相同的特性和行为的对象所归属的类的一部分。程序中使用基本关键字class来引入新的类型。事实上,所有的面向对象程序设计语言都是用class这个关键字来表示数据类型。

    创建抽象数据类型(类)是面向对象程序设计的基本概念之一。

    类描述了具有相同特性和行为的对象集合,一个类实际上就是一个数据类型。

    面向对象方法并不是仅局限于构建仿真程序。面向对象技术的应用确实可以将大量的问题很容易的降解为一个简单的解决方案。

    事实上,面向对象程序设计的挑战之一,就是在问题空间的元素和解空间的对象之间创建一对一的映射。

    每个对象都只能满足某些请求,这些请求由对象的接口(interface)所定义,决定接口的便是类型。

    接口确定了对某一特定对象所能发出的请求。但是,在程序中必须有满足这些请求的代码。这些代码与隐藏的数据一起构成了实现。

    创建一个对象的方式:

    定义这个对象的“引用”(It),然后调用new方法来创建该类型的新对象。为了向对象发送消息,需要声明对象的名称,并以圆点符号链接一个消息请求。

    例如:

String str = new String();//创建对象
str.toString();//发送消息请求

    下图是UML(Unified Modelling Language,统一建模语言)形式的图,每个类都用一个方框表示,类名在方框的顶部,你所关心的任何数据成员都描述在方框的中间部分,方法在方框的底部。通常只有类名和公共方法被展示于UML设计图中。

3、每个对象都提供服务

    当正在试图开发或者理解一个程序设计时,最好的方法之一就是将对象想象为“服务提供者”。程序本身将向用户提供服务,它将通过调用其他对象提供的服务来实现这一目的。你的目标就是去创建能够提供理想的服务来解决问题的一系列对象。

    将对象看作是服务提供者还有一个附带的好处:它有助于提高对象的内聚性。高内聚是软件设计的基本质量要求之一:这意味着一个软件构件的各个方面“组合”的很好。

    将对象作为服务提供者看待是一件维达的简化工具,这不仅仅在设计的过程中非常有用,在其他人理解和重用你的代码时变得简单。

4、被隐藏的具体实现

    程序开发人员按照角色分为类创建者和客户端程序员。(个人理解为:架构师和普通开发人员)

    客户端程序员的目标是收集各种用来实现快速应用开发的类。

    类创建者的目标是构建类,这种类只向客户端程序员暴露必须的部分,而隐藏其他部分。隐藏的部分通常代表对象内部脆弱的部分,它们很容易被粗心或者不知内情的客户端程序员所毁坏,将此隐藏可以减少bug。

    在任何相互关系中,具有关系所涉及的各方都遵守的边界是十分重要的事情。访问控制的第一个存在原因就是让客户端程序员无法触及他们不应该触及的部分。访问控制的第二个存在原因就是允许库设计者可以改变类内部的工作方式而不用担心会影响到客户端程序员。

    Java用三个关键字在类的内部设定边界:public、private、protected。

    public表示紧随其后的元素对任何人都是可用的。(最大权限)

    private表示除了类型创建者和类型的内部方法之外的任何人都不能访问的元素。(最小权限)

    protected表示继承的类可以访问。

    Java还有一种默认的访问权限,不使用任何关键字,这种权限通常被称为包访问权限,只能同包的类可以互相访问其元素,包外的类访问不了包内这种权限的类元素。

5、复用具体实现

    代码复用是面向对象程序设计语言所提供的最了不起的优点之一。

    使用现有的类合成新的类被称为组合(composition),如果组合是动态发生的,那么它通常被称为聚合(aggregation)。组合通常被视为“has-a”的关系。

    组合带来了极大的灵活性,在建立新类时,应该首先考虑组合。

6、继承

    对象这种概念,本身就是十分方便的工具,使得你可以通过概念将数据和功能封装到一起,因此可以对问题空间的观念给出恰当的表示,而不用受制于必须使用底层机器语言,这些概念用关键字class来表示,它们形成了编程语言中的基本单位。

    通过继承可以达到复制原由类并加以改造(添加和修改)创建出新类。原有类被称作基类、超类或者父类,新创建的类被称作导出类、继承类或者子类。

    类型不仅仅只是描述了作用于一个对象集合上的约束条件,同事还有与其他类型之间的关系。

    继承使用基类型和导出类型的概念表示了这种类型之间的相似性。一个基类型包含其导出类型所共享的特性和行为。可以创建一个基类型来表示系统中某些对象的核心概念,从基类型中导出其他类型,来表示此核心可以被实现的各种不同方式。

    例如下图:

    当继承现有类型时,也就是创建了新的类型。这个新的类型不仅包括现有类型的所有成员(尽管private成员被隐藏了起来,并且不可访问),而且更重要的是它复制了基类的接口。也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。这就意味着到处类与基类具有相同的类型。

    由于基类和导出类具有相同的基础接口,所以伴随此接口的必定有某些具体实现。当对象接收到特定的消息时,必须有某些代码去执行。如果只是简单的继承,而不做任何改变的话,这就意味着导出类与基类拥有相同的类型和相同的行为,这样做是没有意义的。

    有两种方法可以使基类和导出类产生差异:

    一是直接在导出类中添加新方法。二是改变现有基类的方法的行为,这被称作覆盖(overriding)。

1.is-a和is-like-a

    如果继承只覆盖基类的方法,就意味着导出类和基类是完全相同的类型,就可以用一个导出来对象来完全替代一个基类对象,这可以被视为纯粹替代,通常称作替代原则。我们经常将这种情况下的基类与导出类之间的关系成为is-a关系。

    判断是否继承,就是要确定是否可以用is-a来描述类之间的关系,并使之具有实际意义。

    如果在导出类型中添加新的接口元素,这样也就扩展了接口。这个新的类型仍然可以替代基类,但是这种替代并不完美,因为基类无法访问新添加的方法。这种情况我们可以描述为is-like-a关系。新类型具有旧类型的接口,但是它还包含其他方法,所以不能说它们完全相同。

​​​​​​​7、伴随多态的可互换对象

    在处理类型的层次结构时,经常想把一个对象不当作它所属的特定类型来对待,而是将其当作其基类的对象来对待。这使得人们可以编写出不依赖于特定类型的代码。

    这样的代码时不会受添加新类型影响的,而且添加新类型是扩展一个面向对象程序以便处理新情况的最常用方式。通过导出新的子类型而轻松扩展设计的能力是对改动进行封装的基本方式之一。这种能力可以极大的改善我们的设计,同时也降低然间维护的代价。

    在试图将导出类型的对象当作其泛化(generic)基类型对象来看待时,仍然存在一个问题:代码执行的时候到底该调用谁?

    一个非面向对象编程的编译器产生的函数调用会引起所谓的前期绑定。前期绑定就是编译器将产生对一个具体函数名字的调用,而运行时将这个调用解析到将要被执行的代码的绝对地址。

    为了解决上述问题,面向对象程序设计语言使用了后期绑定的概念。后期绑定就是当向对象发送消息时,被调用的代码知道运行时才能确定。

    编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查,但是并不知道将被执行的确切代码。无法提供此类保证的语言被称为弱类型语言。

    为了执行后期绑定,Java使用一小段特殊的代码来代替聚堆地址调用。这段代码使用在对象中存储的信息来计算方法体的地址。

    Java中动态绑定是默认行为,不需要添加额外的关键字来实现多态。

    把导出类看做是其基类的过程称为向上转型(upcasting)。

    一个面向对象程序肯定会在某处包含向上转型,因为这是将自己从必须知道确切类型中解放出来的关键。

​​​​​​​8、单根继承结构

    在Java中,所有的类最终都继承自单一的基类,这个终极基类的名称就是Object。

    单根继承的好处:

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

    单根继承结构保证所有对象都具备某些功能。Java中Object类的方法就可以看做是对象都具备的功能。

    单根继承结构使垃圾回收器的实现变得容易得多。

​​​​​​​9、容器

    创建另一种对象类型,这种新的对象类型持有对其他对象的引用,这通常被称作容器,当然也包括数组。

    好的OOP语言都有一组容器,它们作为开发包的一部分。Java在其标准类库中也包含有大量的容器。在某些类库中,一两个通用容器足够满足所有的需求,但是在其他类库中,具有满足不同需求的各种类型的容器。例如:List、Map、Set以及诸如队列、树、堆等更多的构件。

    需要针对容器进行选择有两个原因:

  • 不同容器提供了不同类型的接口和外部行为。
  • 不同的容器对于某些操作具有不同的效率。

1.参数化类型

    Java SE5的重大变化之一就是在增加了参数化类型,在Java中称为泛型。一对尖括号,中间包含类型信息,通过这些特征就可以识别对泛型的使用,例如:

ArrayList<String> strList=new ArrayList<String>();

    泛型规定了容器中存储的数据类型,这样就避免了转型带来的麻烦。

​​​​​​​10、对象的创建和生命期

    Java中完全采用动态内存分配方式。每当需要创建新对象时,使用new关键字累构件对象的动态实例。

    动态方式是在被称为堆(heap)的内存池中动态的创建对象。动态方式可以在需要对象的时候直接在堆中创建。因为存储空间是是正赛运行时被动态管理的,所以需要大量的时间在堆中分配空间。

    动态方式有一个一般性的逻辑假设:对象趋向于变的复杂,所以查找和设防存储空间的开销不会对对象的创建造成重大冲击。

    动态方式所带来的更大的灵活性正是解决一般化编程问题的要点所在。

    Java提供了被称为“垃圾回收器”的机制,它可以自动发现对象何时不再被使用,并继而销毁它。Java的垃圾回收器被设计用来处理内存释放问题。

​​​​​​​11、异常处理:处理错误

    自从编程语言问世以来,错误处理就诗中是最困难的问题之一。

    异常处理将错误处理直接置于编程语言中,有时甚至置于操作系统中。异常是一种对象,它从出错地点被“抛出”,并专门设计用来处理特定类型错误的相应的一场处理器“捕获”。异常不能被忽略,所以保证一定会在某处得到处理。最后需要指出的是:异常提供了一种从错误状况进行可靠恢复的途径。现在不再是只能退出程序,你可以经常进行校正,并恢复程序的执行,这些都有助于编写出更健壮的程序。

    Java一开始就内置了异常处理,而且强制你必须去使用它。它是唯一可接受的错误报告方式。如果没有编写正确的处理异常的代码,那么就会得到一条编译时的出错消息。这种有保障的一致性有时会使得错误处理非常容易。

    异常处理不是面向对象的特征,异常处理在面向对象语言出现之前就已经存在了。

​​​​​​​12、并发编程

    在计算机编程中有一个基本概念,就是在同一时刻处理多个任务的思想。

    并发:把问题切分成多个可独立运行的部分(任务)。

    在程序中这些彼此独立运行的部分称之为线程。线程只是一种为单一处理器分配执行时间的手段。如果操作系统支持多处理器,那么每个任务都可以被指派给不同的处理器,并且他们是在真正的并行执行。

    并发存在一个隐患:共享资源。因此,整个执行过程应该是:某个任务锁定某项资源,完成其任务,然后释放资源锁,使其他任务可以使用这项资源。

    Java的并发是内置于语言中的,Java SE5已经增添了大量额外的库支持。

​​​​​​​13、Java与Internet

    Java对于解决传统的单机程序设计问题非常有用,更重要的是,它解决了在万维网(WWW)上的程序设计问题。

​​​​​​​1.Web是什么

    要理解Web是什么就必须先理解客户/服务器系统。

​​​​​​​1>客户/服务器计算技术

    客户/服务器系统的核心思想是:系统具有一个中央信息存储池(central repository of information),用来存储某种数据,它通常存在于数据库中,你们可以根据需要将它分发给某些人员或机器集群。

    信息存储池、用于分发信息的软件以及信息与软件所驻留的机器或集群被总称为服务器。

    保证一个客户插入的新数据不会覆盖另一个客户插入的新数据,也不会在将其添加到数据可的过程中丢失,这被称为事务处理。

    性能问题:可能在任意时刻都有成百上千的客户向服务器发出请求,所以任何小的延迟都会产生重大影响。为了将延迟最小化,程序员努力减轻处理任务的负载,通常是分散给客户端机器处理,但有时也会使用所谓的中间件将负载分散给在服务器端的其他机器。(中间件也被用来提高可维护性。)

​​​​​​​2>Web就是一台巨型服务器

    Web实际上就是一个巨型客户/服务器系统。

    Web浏览器包含了这样的概念:一段信息不经修改就可以在任意型号的计算机上显示。

    浏览器只是一个观察器,因此它甚至不能执行最简单的计算任务。另一方面,它却是安全的,因为它在你的本地机器上不会执行任何程序,而这些程序有可能包含bug和病毒。

    为了增强浏览器的功能,人们采用了各种不同的方法。首先,图形标准得到了增强,使得在浏览器中可以播放质量更好的动画和视频。

    客户端编程:引入在客户端浏览器中运行程序的能力。

​​​​​​​2.客户端编程

    Web最初的“服务器-浏览器”设计是为了能够提供交互性的内容。但其实交互性完全由服务器提供。服务器产生静态页面,提供给只能解释并显示它们的客户端浏览器。

    基本的HTML(HyperText Markup Language,超文本标记语言)包含有简单的数据收集机制:文本输入框、复选框、单选框、列表和下拉式列表以及按钮——它只能被编程来实现复位表单上的数据或提交表单上的数据给服务器。

    这种提交动作通过所有的Web服务器都提供的通用网关接口(common gateway interface,CGI)传递。提交内容会告诉CGI应该如何处理它。实际上你可以通过CGI做任何事。然而构建于CGI程序之上的网站可能会迅速变得过于复杂而难以维护,并同时产生响应时间过长的问题。CGI程序的响应时间依赖于所必须发送的数据量的大小,以及服务器和Internet的负载,此外启动CGI程序也相当慢。

    客户端编程意味着Web浏览器能用来执行任何它可以完成的工作,使得返回给用户的结果更加迅捷,而且使得你的网站更加具有交互性。

    客户端编程的问题:它与通常意义上的编程十分不同,参数几乎相同,而平台不同。

​​​​​​​1>插件

    客户端编程所迈出的最重要的一步就是插件(plug-in)的开发。通过这种方式,程序员可以下载一段代码,并将其插入到浏览器中适当的位置,以此来为浏览器添加新功能。

    插件对于客户端编程的价值在于:它允许专家级的程序员不需经过浏览器生产厂商的许可,就可以开发某种语言扩展,并将它们添加到服务器中。因此插件也相当于提供了一个“后门”。

​​​​​​​2>脚本语言

    插件引发了浏览器脚本语言(scripting language)的开发。通过使用某种脚本语言,你可以将苦短程序的源代码直接嵌入到HTML页面中,解释这种语言的插件在HTML页面被显示时自动激活。

    优点:相当易于理解,可以被快速加载。

    缺点:代码会暴露给任何人去浏览。

    在Web浏览器内部使用的脚本语言实际上总是被用来解决特定类型的问题,主要是用来创建更丰富、更具有交互性的图形化用户界面(graphic user interface,GUI),脚本语言可以解决客户端编程中所遇到的百分之八十的问题,所以在考虑解决方案的时候应优先考虑脚本语言。

​​​​​​​3>Java

    Java不仅是一种功能强大的、安全的、跨平台的、国际化的编程语言,而且它还在不断地被扩展,以提供更多的语言功能和类库,能够优雅地处理在传统编程语言中很难解决的问题,例如并发、数据库访问、网络编程和分布式计算。

    Java是通过applet以及使用Java Web Start来进行客户端编程的。

    applet是只在Web浏览器中运行的小程序,它是作为网页的一部分而自动下载的。当applet被激活时,它便开始执行一个程序,它提供一种分发软件的方法,一旦用户需要客户端软件时,就自动从服务器把客户端软件分发给用户。用户获取最新版本的客户端软件时不会产生错误,而且也不需要很麻烦的重新安装过程。

    只要一台计算机有浏览器,且浏览器内置了Java解释器,那么这个程序就可以自动在这台计算机上运行。还可以在数据提交之前做数据校验,减少网络带宽的传输。

​​​​​​​4>备选方案

    实际上,applet并没有大规模的应用,有以下几个原因:

    1.安装Java运行时环境(JRE)必须10M带宽。

    2.微软没有在IE(Internet Explorer)中包含JRE

    那么就需要几个备选方案:

    Macromedia的Flex,它允许你创建基于Flash的与applet相当的应用,Flash Player在超过98%的Web浏览器上都可用,所以编程时无需担心浏览器的相关性。

    ActionScript语言是基于ECMAScript的。

​​​​​​​5>.NET和C#

    曾经,Java applet的主要竞争对手是微软的ActiveX。ActiveX要求客户端必须运行在Windows平台。

    .NET平台大致相当于Java虚拟机(JVM)和Java类库,而C#毫无疑问与Java有类似之处。

    .NET最受关注的问题就是微软是否允许将它完全地移植到其他平台。微软宣称这么做没有问题,而且Mono项目已经有一个在Linux上运行的.NET的部分实现,但是还不稳定。

​​​​​​​6>Internet与Intranet

    Web是最常用的解决客户端/服务器问题的方案,可以解决以下问题:

    1.客户端计算机多种型号。

    2.安装软件的麻烦。

    3.软件升级的麻烦,浏览器方式下的升级是透明的、自动的。

    当Web技术仅限于特定公司的信息网络时,它被称为Intranet(企业内部网)。Intranet比Internet提供了更高的安全性,因为可以屋里地控制对公司内部服务器的访问。在Intranet上,你可以对自己的代码质量负责,并且在发现bug之后可以修复它们。

    当面对各种令人眼花缭乱的解决客户端编程问题的方案时,最好的方法就是进行性价比分析。认真考虑问题的各种限制,然后思考那种解决方案可以成为最短的捷径。

​​​​​​​3.服务器端编程

    Java取得巨大成功的因素之一就是服务器端编程。

    涉及到对数据库的修改,这些数据可请求必须通过服务器端的某些代码来处理,这就是所谓的服务器端编程。

    基于Java的Web服务器使用Java编写被称为servlet的程序来实现服务器端编程。servlet及其衍生物JSP,是许多开发网站的公司迁移到Java上的两个主要的原因,尤其是因为他们消除了处理具有不同能力的浏览器时所遇到的问题。

    服务器端编程的具体介绍请看《企业Java编程思想》。

​​​​​​​14、总结

    编写良好的Java程序通常比过程型程序要简单得多,而且也易于理解得多。

    使用Java只需要关心以下两部分内容的定义:用来表示问题空间概念的对象,以及发送给这些对象的用来表示在此空间内的行为的消息。

    对于设计良好的程序,通过阅读它就可以很容易地理解其代码。通常,其代码也会少很多,因为许多问题都可以通过重用现有的类库代码而得到解决。

    个人总结

    此章内容,将Java从头到尾大致上介绍了一遍,如果是初学者,肯定会很懵,只有对Java有一定了解的人,才能有些理解,对初学者的建议是忽略此章,从第二章开始学习,最后,再来看此章节。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/07/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一章:对象导论
  • 1、抽象过程
  • 2、每个对象都是一个接口
  • 3、每个对象都提供服务
  • 4、被隐藏的具体实现
  • 5、复用具体实现
  • 6、继承
    • 1.is-a和is-like-a
    • ​​​​​​​7、伴随多态的可互换对象
    • ​​​​​​​8、单根继承结构
    • ​​​​​​​9、容器
      • 1.参数化类型
      • ​​​​​​​10、对象的创建和生命期
      • ​​​​​​​11、异常处理:处理错误
      • ​​​​​​​12、并发编程
      • ​​​​​​​13、Java与Internet
        • ​​​​​​​1.Web是什么
          • ​​​​​​​1>客户/服务器计算技术
          • ​​​​​​​2>Web就是一台巨型服务器
        • ​​​​​​​2.客户端编程
          • ​​​​​​​1>插件
          • ​​​​​​​2>脚本语言
          • ​​​​​​​3>Java
          • ​​​​​​​4>备选方案
          • ​​​​​​​5>.NET和C#
          • ​​​​​​​6>Internet与Intranet
        • ​​​​​​​3.服务器端编程
        • ​​​​​​​14、总结
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档