龙空技术网

java 核心技术12版卷1 - 1.2 Java 白皮书的关键术语

CC躺平混吃 70

前言:

现时大家对“java核心技术卷一”大致比较关心,我们都想要分析一些“java核心技术卷一”的相关内容。那么小编在网摘上汇集了一些关于“java核心技术卷一””的相关内容,希望大家能喜欢,各位老铁们快快来学习一下吧!

原文

Java 的设计者编写了一个颇有影响力的白皮书,来结束设计初衷以及完成的情况,他们还发布了一个简短的摘要。这个摘要按以下11个关键术语进行组织:

简短性面向对象分布式健壮性安全性体系结构中立可移植性解释性高性能多线程多态性

注释:白皮书可以在  上找到。关于11个关键术语的概述请参见 

1.2.1 简单性

我们希望构建一个无须深奥的专业训练就可以进行编程的系统,并且要符合当今的标准惯例。因此,尽管我们发现C++不太适用,但在设计Java的时候还是尽可能地接近C++,以使系统更易于理解。Java 剔除了C++中许多很少使用、难以理解、容易混淆的特性。在我们看来,这些特性带来的问题远远多于它们的好处。

个人补充说明:有一种说法,Java 被戏称为C++--,就是因为java 在设计之时参考了C++,但又裁剪了很多东西。但需要注意的是,这些裁剪更多的是语法设计层面的,现在以就业为目标学习java 决不能仅限于Java语法。随着java 这些年来的发展,大家也不得不“卷”起来,而“卷”也大致分为两个方向:1. 底层: java 底层如何实现,jvm 如何执行和优化2. 框架: 很多人也戏称java 工程师为“Spring 工程师”,就是Spring 对java 的影响太大了,以至于很多面试题都要考察Spring 系列框架(SpringBoot ,SpringCloud 为基础的分布式架构),包括源码,原理,分布式理论等

的确,Java 语法是C++语法的一个“纯净”版本。这里没有头文件、指针运算(甚至没有指针语法)、结构、联合、操作符重载、虚基类等(请参阅本书各个章节给出的C++注释,其中比较详细地解释了Java 和C++之间的区别)。不过Java 设计者并没有试图修正C++中所有不适当的特性。例如,switch语句的语法在java 中就没有改变。如果你了解C++,会发现可以轻而易举地转换到Java 语法。

个人补充:switch语法个人也觉得比较反人类,因为默认switch跳转到指定语句之后,并不是只执行指定的case 中语句,而是默认继续向后继续执行所有的代码,直到执行完整个switch 或者遇到 break语句。当然,这么设计自有原因,也有人会提出这么做的合理性,但对于很多初次接触这种语法的人来说,必须在case语句末尾添加break,很让人费解和容易遗漏。

Java发布时,实际上C++并不是最常用的程序设计语言。很多开发人员都在使用Visual Basic和它的拖放式编程环境。这些开发人员并不觉得Java简单。很多年之后Java开发环境才迎头赶上。如今,Java开发环境已经远远超越了大多数其他编程语言的开发环境。

“简单”的另一面是“小”。Java的目标之一是支持开发能够在小型机器上独立运行的软件。基本的解释器和类支持大约仅为40KB,再加上基础的标准类库和线程支持(基本上是一个自包含的微内核),大约需要增加175KB。

在当时,这是一个了不起的成就。当然,由于不断的扩展,类库已经相当庞大了。现在还有一些带有较小类库的独立版本,这些版本适用于嵌入式设备和智能卡。

个人补充:现在随着版本更新,Java当然已经远远超过了当时的大小,并且,Java现在也几乎放弃了嵌入式环境,现在Java最大的市场是web开发,Java的类库也在这方面有了长足的发展,各方面开源框架非常丰富,大大简化了开发工作。

1.2.2 面向对象

简单地讲,面向对象设计是一种程序设计技术。它将重点放在数据(即对象)和对象的接口上。用木匠打一个比方:一个“面向对象的”木匠主要关注的是所制作的椅子,其次才是使用的工具;一个“非面向对象的”木匠主要考虑的则是使用的工具。在本质上,Java的面向对象能力与C++是一样的。

开发Java时面向对象技术已经相当成熟。Java 的面向对象特性与C++旗鼓相当。Java与C++的主要不同点在于多重继承,在Java中,取而代之的是更简单的接口概念。与C++相比,Java提供了更丰富的运行时自省功能(有关内容将在第5章中讨论)。

个人补充:面向对象的概念现在不需要着急去理解,随着对Java 的理解深入,对Java的优缺点自然会越来越明白。

1.2.3 分布式

Java有一个丰富的例程库,用于处理HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网上的对象,其便捷程度就好像访问本地文件一样。

如今这一点被认为是理所当然的,不过在1995年主要还是C++或Visual Basic程序连接Web服务器。

个人补充:Java不仅在自带的库中提供了网络访问功能(旧版jdk中的HttpURLConnection 和自jdk11开始发布的HttpClient),并且开源社区也提供了很多Http 和 FTP之类的库,更加方便地进行相关开发。在现在,我们或许可以把“分布式”这个概念进一步扩展,通过SpringCloud ,dubbo和 Alibaba 等分布式框架,Java在分布式-微服务的互联网大数据领域同样大展身手,不再只是简单地通过TCP/IP做一些简单的访问,而是构建分布式应用,以适应数据量,并发量急速膨胀的互联网应用环境

1.2.4 健壮性

Java的设计目标之一是要让Java编写的程序具有多方面的可靠性。Java非常强调进行早期的问题检测、后期的动态(运行时)检测,以及消除容易出错的情况……Java与C/C++最大的不同在于Java采用的指针模型可以消除重写内存和损坏数据的可能性。

Java编译器能够检测许多其他语言中仅在运行时才能够检测出来的问题。至于第二点,对于曾经花费几个小时来检查由于指针bug而引起内存冲突的人来说,一定很喜欢Java的这一特性。

个人补充:Java是静态强类型语言,并且,因为Java的语法严谨,Java的ide可以做的非常强大,在开发阶段就能避免很多问题。而因为1.2.1中的简单性,Java 去除了一些容易造成问题的特性,在稍微牺牲极端条件下的最高性能的同时,大大提高了安全性和下限。或者,可以这么说,最优秀的C/C++程序员可以开发出用Java 无法满足性能要求的应用,这是语言本身的特点所决定的,C/C++的性能上限自然是超过Java的。但对于普通的应用,使用Java 可以保证使用一般的程序员就能做出不会太差的应用。这也是Java受欢迎的原因——绝大多数公司只能/只需要 使用普通程序员,开发出一般的应用。就像谁都知道清华、北大的学生很优秀,但大多数公司招不到,只能在合适的范围内招聘。同样的普通程序员,使用Java 有了IDE 和语言本身的兜底,在出错方面会减少很多。

1.2.5 安全性

Java要适用于网络/分布式环境。为了实现这个目标,安全性颇受重视。使用Java可以构建防病毒、防篡改的系统。

从一开始,Java就设计成能够防范各种攻击,其中包括:

运行时堆栈溢出,这是蠕虫和病毒常用的攻击手段。破坏自己的进程空间之外的内存。未经授权读写文件。

注释:现在看来,尽管Java 安全模型没有原先预想的那么成功,但Java 在那个时代确实相当超前。微软公司提出了一种与之竞争的代码交付机制,成为ActiveX,其安全性完全依赖于数字签名。显然这是不够的,因为微软公司的产品的任何用户都可以证实,一些知名开发商的程序确实会崩溃并对系统产生危害。

个人补充:Java的安全性主要源于两个方面,jvm机制和jdk的安全设计* jdk的安全设计不必赘述,任何一种语言都会在安全方面做出设计和限制,以尽可能避免一些安全问题,java自然也不例外* jvm 即Java Virtual Machine,也就是Java 虚拟机。Java的代码经过编译(javac)之后,成为class文件,这种文件才是Java的可执行文件。Java的文件需要在jvm中执行,Java通过jvm 机制,将执行过程放在一个专门实现的环境中,而不是直接在操作系统中执行。这样,即便是jvm系统崩溃,也不会直接影响到操作系统,从而避免了很多安全问题。

1.2.6 体系结构中立

编译器生成一个体系结构中立的目标文件格式,这是一种编译型代码,这些编译型代码可以在很多处理器上运行(只要它们有Java 运行时系统)。Java 编译器通过生成与特定计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易地在任何机器上解释执行,而且可以很容易地动态转换为原生机器代码。

当时为“虚拟机”生成代码并不是一个新思路,诸如Lisp、Smalltalk和Pascal 等编程语言多年前就已经采用了这种技术。

当然,解释虚拟机指定肯定比全速运行机器指令慢很多。不过,虚拟机有一个选项,可以将执行最频繁的字节码序列转换成机器码,这一过程称为即时编译(just-in-time-compilation)。

Java 虚拟机还有其他一些优点。它可以检查执行序列的行为,从而增强安全性。

个人补充:Java的体系结构中立是其他特性的底层支撑。换言之,可以理解为体系结构中立是手段,而不是目标。通过中立,可以达到在多种处理器,多种系统中实现相同或者至少非常相近的效果。将代码放在虚拟机中执行,可以避免代码直接破坏主系统内存,更加安全。对于开发者来说,不需要关心不同的操作系统的差异,只需要按照虚拟机的规范开发代码即可(除非开发者需要直接对接操作系统,这种情况其实用native 方法实现,Java调用更合适,而这种严格来说其实已经不是Java的范畴。)至于不同系统之间的区别部分,由jvm/jdk来解决。比如,windows 版的jdk 提供了专用于windows 的jvm,linux系统则有linux版的jdk/jvm。程序员唯一需要做的就是在不同的系统下,安装不同的jdk。如此一来,大大简化了程序员的兼容工作,移植等工作也更简单,安全方面也更容易保护。

1.2.7 可移植性

与C和C++不同,Java规范中没有“依赖具体实现”的地方。基本数据类型的大小以及有关运算的行为都是明确的。

例如,Java中的int总是32位整数,而在C/C++中,int可能是16位整数、32位整数,也可能是编译器开发商指定的任何其他大小。唯一的限制是,int类型的字节数不能低于short int,并且不能高于long int。Java中,数值类型有固定的字节数,这消除了代码移植时一个令人头痛的主要问题。二进制数据以固定的格式进行存储和传输,消除了有关字节顺序的困扰。字符串则采用标准的Unicode 格式存储。

作为系统组成部分的类库定义了可移植的接口。例如,有一个抽象 Window 类,并给出了面向 UNIX、Windows 和 Macintosh 环境的不同实现。

选择 Window 类作为例子可能并不太合适。凡是尝试过的人都知道,要编写一个在Windows、Macintosh 和 10 种不同风格的 UNIX 上看起来都不错的程序是多么困难。Java 1.0就尝试着做了这么一个壮举,发布了一个简单的工具包,为多个不同平台提供了常用的用户界面元素。遗憾的是,尽管花费了大量的心血,结果却不尽如人意,这个库并不能在不同系统上都提供让人接受的结果。原先的用户界面工具包已经重写,而且后来又再次重写,跨平台的可移植性仍然是个问题。

不过,除了与用户界面有关的部分外,所有其他 Java 库确实能很好地支持平台独立性。你可以处理文件、正则表达式、XML、日期和时间、数据库、网络连接、线程等,而不用操心底层操作系统。不仅程序是可移植的,Java API 往往也比原生 API 质量更高。

个人补充:       可移植性是Java的非常重要的特性,这一点也是通过jvm来实现的。Java 通过虚拟机隔离了不同系统底层的差异,将这些差异内容通过不同系统下的jvm 来进行实现,对于Java程序员来说,不需要去研究这些系统,只需要理解好Java的api即可。        对于Java来说,只要jdk版本符合要求,依赖的jar包(也就是其他人开发的程序打包而成的二进制文件)不管在linux ,windows 或者 mac 系统下都是一样的。        与之相反,windows 的 exe 程序是不可能在linux 下执行的,只能通过 wine 等,或者干脆使用源码重新编译——当然,很多时候不是简单重新编译就可以的,因为这种程序往往用了很多windows 的系统接口,需要修改到linux 的相应的API 或者ABI

1.2.8 解释性

Java 解释器可以在任何移植了解释器的机器上直接执行 Java 字节码。由于链接(linking)是一个增量式的轻量级过程,所以,开发过程也会更加快捷,更具有探索性。

这看上去很不错。用过 Lisp、Smalltalk、Visual Basic、Python、R 或 Scala 的人都知道“快捷而且具有探索性”的开发过程是怎样的。你可以做些尝试,然后立即就能看到结果。在 Java 发展的前 20 年里,开发环境并没有把重点放在这种体验上。直到 Java 9 才提供了jshell 工具来支持快捷而且具有探索性的编程。

个人补充:    这一点目前来说并不是重点,就不做过多解释了。不过,上面提到java 9 才提供 jshell 也进一步说明了之前咱们提到的“新特性推出非常谨慎,新功能推出速度稍慢”。Java为了保证兼容和稳定,对于新功能非常地克制,很多功能与特性都是反复推敲之后才推出。(不过,最近oracle似乎打算改变这一点,jdk现在每半年推出一个短期版本,每三年,也就是6个版本中,会推出一个lts版本,最新的lts版本就是17。如果是学习者,可以关注这些短期版本,了解Java的新趋势。如果是打算在公司中正式使用,还是要非常谨慎,在lts中选择。)

1.2.9 高性能

尽管解释型字节码的性能通常已经足够让人满意,但在有些场合下还需要更高的性能。字节码可以(在运行时)动态转换为面向运行这个应用的特定 CPU 的机器码。解释器可以在任何移植了解释器的机器上直接执行Java 字节码。由于链接(linking)是一个增量式的轻量级过程,所以,开发过程也会更加快捷,更具有探索性。

使用 Java 的头几年,许多用户不同意“性能已经足够让人满意”的说法。不过,现在的即时编译器已经非常出色,可以与传统编译器相媲美,而且在某些情况下甚至超越了传统编译器,原因是它们有更多的可用信息。例如,即时编译器可以监控哪些代码频繁执行,并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“内联”)。即时编译器知道已经加载了哪些类。基于当前加载的类集合,如果一个特定的函数不会被覆盖,就可以使用内联。必要时,以后还可以撤销这种优化。

个人补充:    Java的第一个版本jdk1.0推出时,问题很多,并且是纯解释型,使用外挂的jit,性能很差。不过在后续的版本中,Java不断优化,在性能方面有了长足进步。在早期的时候,Java开发者在面对性能问题时,经常不得已使用C、C++编写关键的计算部分,使用native方法调用。现在已经很少这样了,Java的高性能已经越来越成为事实——虽然可能无法完全媲美C/C++,但绝大多数情况已经完全足够。

1.2.10 多线程

多线程可以带来更好的交互响应和实时行为。

如今,我们非常关注并发性,因为摩尔定律即将走到尽头。我们不再追求更快的处理器,而是着眼于获得更多的处理器,而且要让它们保持繁忙。不过,可以看到,大多数编程语言对于这个问题并没有显示出足够的重视。

Java在当时很超前。它是第一个支持并发程序设计的主流语言。从白皮书中可以看到,它的出发点稍有些不同。当时,多核处理器还很神秘,而Web编程才刚刚起步,处理器要花很长时间等待服务器的响应,需要并发程序设计来确保用户界面没有“冻住”。

并发程序设计绝非易事,不过Java在这方面表现很出色,可以很好地管理这个工作。

个人补充:    成大事者往往实力与运气兼具,Java发展到现在一样有很多阴差阳错的机遇。Java的前身oka 本来打算用于小型设备,但并未成功。之后却赶上了互联网开发的热潮,Java 通过 applet 得到了一波发展。在之后的时间里,applet 因为种种原因输给了flash,最终退出了在网页上的竞争。但在后续,Java因为兼容性,健壮性,可移植性,高性能等方面都足够优异,并且,虽然语法稍显啰嗦,但在ide 的辅助下,开发非常方便,成为了很多公司应用后台的首选。在过去的二十多年中,Java在编程语言中常常占据前五,甚至前三的位置,选择Java ,意味着只要你的能力没有问题,找到一份工作,甚至是好工作,并不是什么难事,而不太主流的语言在择业上则往往非常受限。

1.2.11 动态性

从很多方面来看,Java与C或C++相比更具有动态性。Java设计为能够适应不断演进的环境。库可以自由地添加新方法和实例变量,而对客户端没有任何影响。在Java中找出运行时类型信息十分方便。

需要为正在运行的程序增加代码时,动态性将是一个非常重要的特性。一个很好的例子是:在浏览器中运行从Internet下载的代码。如果使用C或C++,这确实难度很大,不过Java设计者很清楚动态语言可以很容易地让一个正在运行的程序实现演进。最终,他们将这一特性引入到这个主流程序设计语言中。

注释:Java 成功地推出后不久,微软就发布了一个叫作J++的产品,它与Java有几乎相同的编程语言和虚拟机。现在,微软不再支持J++,取而代之的是另一个名为C#的语言。C#与Java有很多相似之处,不过在一个不同的虚拟机上运行。本书不准备介绍J++或C#语言。

标签: #java核心技术卷一