Thinking in Java阅读笔记(一)

2024-06-22 05:48
文章标签 java 笔记 阅读 thinking

本文主要是介绍Thinking in Java阅读笔记(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第一章:对象导论

抽象化的过程

汇编语言仅对底层的实体机器进行少量抽象化。许多所谓命令式程序语言(Fortran、BASIC、C),则在汇编语言之上再抽象化。此类语言大幅改进了汇编语言,但他们所做的主要是机器本身的抽象化,你依旧无法逃脱“以电脑结构进行问思考”的命运,因而无法以待解决问题的结构来作为思考基准。程序设计者必须自行建立介于机器模型和实际待解问题模型之间的关联性。这里头需要的便是“对映”功夫,然而这种能力并非程序语言的自性本质,这使得程序难以撰写,维护代价高昂。

个人理解:非面向对象的语言都是要程序员以机器的角度出发,解决实际问题,要把实际问题转换成适应机器的方式,来让机器解决。

面向对象法更进一步,提供各式各样的工具,让程序设计者得以在题域中表现必要的元素。我们将题域中的元素和其在解域中的表述称为“对象”。当你阅读解法程序的代码时,便如同阅读问题本身的表述一样。这种语言比我们过去所拥有的任何语言具备更弹性更威力的抽象化机制。因此OOP提供了以问题描述问题的能力,而不再是以解答执行之所在(电脑)的形式来描述问题。


重复运用实现码

想要重复运用某个class,最简单的方式莫过于直接使用其所产生的对象,此外你也可以把某个class对象置于另一个class内。我们称这种形式为“产生一个成员对象”。新的classes可由任意数目、任意型别的它种对象组成,这些对象可以任何组合方式到达你想要的功能。由于这种方式是“以既有的classes合成新的class”,所以这种观念被称为“组合(composition)或聚会(aggregation)”。组合通常被视为“has-a”的关系,就好像我们说“车子拥有引擎”。


(以上UML图以实心菱形指向车子,代表组合关系)

继承:重复运用接口
(以上UML图中的箭号,是从derived class 指向base class,表示继承)
当你继承既有的type时,便创造了新的type,后者不仅包含前者的所有成员(private成员会被隐藏,而且无法访问),更重要的是它也同时复制了base class的接口。也就是说, 所有可以发送给base class对象的消息,也都同样可以发送给derived class对象 。通过继承而发送的型别等价性,是了解面向对象程序设计精髓的重要关键。
两种做法可以产生derived class与base class之间的差异。第一种做法,只要直接在derived class中增加新函数即可。这些新函数并非base class接口的一部分。这意味着base class无法满足你的需要,因此你得加入更多函数。这种既简单又基本的方式,有时候对你的问题而言是一种完美的解答。但是你应该仔细思考, 你的base class是否也可能需要这些额外功能 。这种发现与更替的过程,会在整个面向对象设计过程中持续发生。
形成差异的第二种方法(也许是更重要的方法)便是改变既有之base class的函数行为,这种行为我们通常称为“覆写(overriding)”。

随多态而生的可互换对象
由non-oop编译器所产生的函数调用,会以所谓“前期绑定”方式来调用函数,运用这种方式,编译器对调用动作产生出特定的函数名称,而联结器(linker)再将此调用动作协议为“欲执行之程序代码的绝对地址”,但是在oop中,程序未到执行期是无法决定程序代码的地址的,因此当我们将消息发送给泛化对象(generic object)时,必须采用其他解决方案。
为解决上述问题, 面向对象程序语言采用所谓的“后期绑定”观念。为了达到后期绑定,Java使用一小段特殊程序代码来代替调用动作的绝对形式。这一小段程序代码会通过对象内存储的信息来计算函数实体地址。Java的所有函数,除了被声明final者,皆使用后期绑定。这意味着在一般情况下,你不需要判断后期绑定动作何时发生——他会自动发生。 将某个函数声明为final可以“关闭”动态绑定。
在某些程序语言里头(例如C++),你得明确指出是否希望某个函数具备后期绑定的弹性。这一类语言把所有的member functions的绑定动作缺省为“非动态”。这会引起诸多问题,所以Java将所有member functions缺省绑定为动态绑定(后期绑定),你不需要加上任何关键字,就可以获得多态(polymorphism)的威力。
我们把“将derived class 视为其 base class”的过程,称为“向上转型upcasting”。

抽象基类与接口
通常在一个设计案中,你会希望base class仅仅代表其derived class 的接口。也就是说,你不会希望任何人产生base class的实际对象,而只希望他们向上转型至base class——这使得其接口可以派上用场。如果这确实是你的愿望,可以使用关键字abstract来标示某种class是“抽象的”。你也可以使用abstract来描述“目前尚未实现完全”的函数。
关键字interface又更进一步的发挥抽象概念,阻止任何一个函数被定义出来。interface是个常被用到而又十分方便的工具,因为它提供了“接口和实现分离”的完美境界。此外,如果你想要,你可以将多个接口组合在一起,不过你无法同时继承多个一般的或抽象的classes。

对象的形貌与寿命
对象的数据存于何处?它的寿命如何控制?这里有一些不同的处理哲学。C++认为效率是最重要的议题,因此将抉择留给程序控制者。 想要取得最好的执行速度?没问题,请将对象置于stack或静态存储区中 ,于是程序撰写时便决定了对象的存储空间和寿命。这种安排是把重点摆在存储空间的分配与释放的速度上。某些情况下这样的安排可能很有价值,不过这么做也牺牲了弹性,因为你必须在程序撰写期间明确知道对象的数量、寿命、型别。
第二种方法是从一块名为heap(堆)的内存中动态产生对象。在这种方式下,除非等到执行期,否则你无法回答需要多少对象、寿命如何、确切型别为何等问题。这些问题只有程序执行时方能给出答案。
还有一个议题就是对象的寿命。在那些“允许对象诞生于stack内”的程序语言中,编译器会判断对象应该存活多久,并可自动消灭之。但如果在heap之中生成对象,编译器对其寿命将一无所知。以C++为例,你得自行撰写程序代码来摧毁对象。因此如果不能正确做好此事,就会引发内存泄露(memory leaks),这几乎是C++程序的共通问题。Java 提供了所谓“垃圾回收器”机制,当对象不再被使用,会被自动觉察并消灭。 垃圾回收器十分便利,因为它可以减少你需要考量的因素,也减少你必须撰写的程序代码数量,更重要的是,垃圾回收器提供了更高阶的保障,避免隐晦的内存泄露问题发生。

单根继承体系
单根继承体系保证所有对象都拥有某些功能,在整个系统里,你因此知道可以在每个对象身上执行某些基本操作。单根继承体系再加上“在heap之中产生所有对象”,大大简化了引数(arguments)传递动作(这是C++里头十分复杂的问题之一)。
单根继承体系也使垃圾回收器(内置于Java)的实现更加容易。所有必备功能都可安置于base class身上,然后 垃圾回收器便可发送适当消息给系统中的每个对象。由于所有对象都会保证有执行期型别信息,所以你必不会因为无法判断对象的确切型别而陷入动弹不得的僵局 。对于异常处理之类的系统级操作行为而言,这一点格外重要,并且也能为程序设计带来更佳弹性。

这篇关于Thinking in Java阅读笔记(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083466

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2