Java核心技术卷1(第十二版)
▲Java程序设计平台
▲Java白皮书的关键术语
▲Java applet与Internet
▲Java发展简史
▲关于Java的常见误解
在《Java核心技术》第一版中,Gary Cormnell是这样描述Java的:
“作为一种计算机语言,Java的广告词确实有点夸大其词。当然,Java 的确是,一种优秀的程序设计语言。作为一个名副其实的程序设计人员,使用Java无疑是一个比较好的选择。我们认为: Java 本来有潜力成为一种卓越的程序设计语言,但可能有些为时过晚。一旦一种语言得到广泛应用,与现存代码尴尬的兼容性问题就摆在了人们的面前。”
关于这段文字,我们的编辑受到Sun公司某高层人士的严厉批评( Sun是最早开发Java的公司)。Java 有许多非常优秀的语言特性,本章稍后会详细地讨论这些特性。但它确实也有缺点,由于兼容性需求,新增的一些特性就没有原有的特性那么精巧。但是,正像我们在第1版中所说的,Java 并不只是一一种语言。在此之前出现的那么多种语言都没有引起那么大的轰动。Java 是一个完整的平台,有一个庞大的库,其中包含了大量可重用的代码,还有一个提供诸如安全性、跨操作系统的可移植性以及自动垃圾收集等服务的执行环境。
作为一名程序设计人员,你可能希望能有这样-一种语言,既要有令人舒适的语法,也要有易于理解的语义(C++就不是这样的语言)。Java完全满足这些要求,另外还有很多其他优秀语言也能满足要求。不过尽管有些语言提供了可移植性、垃圾收集等特性,但它们没有提供一个丰富的库。如果你想要酷炫的绘图功能、网络连接或数据库存取特性,就必须自动手编写代码。而Java一应俱全,它具备所有这些特性,是一种功能齐全的出色语言和一个高质量的执行环境,同时有一个庞大的库。正是因为Java集多种优势一身,所以对广大程序设计人员有着不可抗拒的吸引力。
1)简单性 | 5)安全性 | 9)高性能 |
---|---|---|
2)面向对象 | 6)体系结构中立 | 10)多线程 |
3)分布式 | 7)可移植性 | 11)动态性 |
4)健壮性 | 8)解释性 |
白皮书可以在 www.oracle.com/technetwork/java/langenv-140151.html上找到。
关于 11 个关键术语的概述请参见 http://horstmann.com/corejava/java-an-overview/7Gosling.pdf
我们希望构建一个无须深奥的专业训练就可以进行编程的系统,并且要符合当今的标准惯例。因此,尽管我们发现C++不太适用,但在设计Java的时候还是尽可能地接近C++,以使系统更易于理解。Java剔除了C++中许多很少使用、难以理解、容易混淆的特性。在我们看来,这些特性带来的问题远远多于它们的好处。
的确,Java 语法是C++语法的一个“纯净”版本。这里没有头文件、指针运算(甚至没有指针语法)、结构、联合、操作符重载、虛基类等。不过, Java设计者并没有试图修正C++中所有不适当的特性。例如,switch 语句的语法在Java 中就没有改变。
Java发布时,实际上C++并不是最常用的程序设计语言。很多开发人员都在使用VisualBasic和它的拖放式编程环境。这些开发人员并不觉得Java简单。很多年之后Java 开发环境才迎头赶上。如今,Java 开发环境已经远远超越了大多数其他编程语言的开发环境。
“简单”的另一面是“小”。Java的目标之一是支持开发能够在小型机器上独运行的软件。基本的解释器和类支持大约仅为40KB,再加上基础的标准类库.
和线程支持(基本上是一个自包含的微内核),大约需要增加175KB。
在当时,这是一个了不起的成就。当然,由于不断的扩展,类库已经相当庞大了。现在还有一些带有较小类库的独立版本,这些版本适用于嵌入式设备和智能卡。
简单地讲,面向对象设计是一种程序设计技术。它将重点放在数据(即对象)和对象的接口上。用木匠打一个比方:一个“面向对象的”木匠主要关注的是所制作的椅子,其次才是使用的工具;一个“非面向对象的”木匠主要考虑的则是使用的工具。在本质上,Java的面向对象能力与C++是一样的。
开发Java时面向对象技术已经相当成熟。java的面向对象特性与C++旗鼓相当。Java 与C++的主要不同点在于多重继承,在Java中,取而代之的是更简单的接口概念。与C++ 相比,Java提供了更丰富的运行时自省功能。
Java有一个丰富的例程库,用于处理HTTP和FTP之类的TCP/IP协议。Java 应用程序能够通过URL打开和访问网上的对象,其便捷程度就好像访问本地文件一样。
如今,这一点被认为是理所当然的,不过在1995年主要还是从C++或Visual Basic程序连接Web服务器。
Java的设计目标之一是要让用Java编写的程序具有多方面的可靠性。Java非常强调进行早期的问题检测、后期的动态(运行时)检测,以及消除容易出错的情况……Java与C/C++最大的不同在于Java采用的指针模型可以消除重写内存和损坏数据的可能性。
Java编译器能够检测许多其他语言中仅在运行时才能够检测出来的问题。至于第二点, 对于曾经花费几个小时来检查由于指针bug而引起内存冲突的人来说,一定很喜欢Java的这 一特性。
Java要适用于网络/分布式环境。为了实现这个目标,安全性颇受重视。使用 Java可以构建防病毒、防篡改的系统。
现在看来,尽管Java安全模型没有原先预想的那么成功,但Java在那个时代确实相当超前。微软公司提出了一种与之竞争的代码交付机制,称为ActiveX,其安全性完全依赖于数字签名。显然这是不够的,因为微软公司的产品的任何用户都可以证实,一些知名开发商的程序确实会崩溃并对系统产生危害。
编译器生成一个体系结构中立的目标文件格式,这是一种编译型代码,这些编译型代码可以在很多处理器上运行 (只要它们有 Java 运行时系统)。Java 编译器通过生成与特定计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易地在任何机器上解释执行,而且可以很容易地动态转换为原生机器代码。
当时,为“虚拟机”生成代码并不是一个新思路,诸如 Lisp、Smalltalk 和 Pascal 等编程语言多年前就已经采用了这种技术。
当然,解释虚拟机指令肯定比全速运行机器指令慢很多。不过,虚拟机有一个选项,可以将执行最频繁的字节码序列转换成机器码,这一过程称为即时编译 (just-in-timecompilation)。
Java 虚拟机还有其他一些优点。它可以检查指令序列的行为,从而增强安全性。
与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解释器可以在任何移植了解释器的机器上直接执行Java字节码。由于链接 (linking)是一个增量式的轻量级过程,所以,开发过程也会更加快捷,更具有探索性。
这看上去很不错。用过 Lisp、Smalltalk、Visual Basic、Python、R或Scala 的人都知道“快捷而且具有探索性”的开发过程是怎样的。你可以做些尝试,然后立即就能看到结果。在 Java 发展的前 20 年里,开发环境并没有把重点放在这种体验上。直到 Java 9才提供了jshel1 工具来支持快捷而且具有探索性的编程。
尽管解释型字节码的性能通常已经足够让人满意,但在有些场合下还需要更高的性能。字节码可以 (在运行时)动态转换为面向运行这个应用的特定 CPU的机器码。
使用 Java 的头几年,许多用户不同意“性能已经足够让人满意”的说法。不过,现在的即时编译器已经非常出色,可以与传统编译器相媲美,而且在某些情况下甚至超越了传统编译器,原因是它们有更多的可用信息。例如,即时编译器可以监控哪些代码频繁执行,并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“内联”)。即时编译器知道已经加载了哪些类。基于当前加载的类集合,如果一个特定的函数不会被覆盖,就可以使用内联。必要时,以后还可以撤销这种优化。
多线程可以带来更好的交互响应和实时行为。
Java 在当时很超前。它是第一个支持并发程序设计的主流语言。从白皮书中可以看到,它的出发点稍有些不同。当时,多核处理器还很神秘,而 Web 编程才刚刚起步,处理器要#很长时间等待服务器的响应,需要并发程序设计来确保用户界面没有“冻住”。
并发程序设计绝非易事,不过Java 在这方面表现很出色,可以很好地管理这个工作
从很多方面来看,Java与C或 C++ 相比更具有动态性。Java 设计为能够适应不断演进的环境。库可以自由地添加新方法和实例变量,而对客户端没有任何影响。在 Java 中找出运行时类型信息十分简单。
Java成功地推出后不久,微软就发布了一个叫作J++ 的产品,它与 Java 有几乎相同的编程语言和虚拟机。现在,微软不再支持J++,取而代之的是另一个名为 C#的语言。C# 与Java 有很多相似之处,不过在一个不同的虚拟机上运行。
这里的想法很简单:用户从Internet 下载 Java字节码,并在自己的机器上运行。在网页中运行的Java 程序称为 applet。要使用applet,只需要一个启用 Java 的 Web 浏览器,它会为你执行字节码。不需要安装任何软件。只要你访问包含 applet 的网页,都会得到这个程序的最新版本。最重要的是,归功于虚拟机的安全性,我们不必担心来自恶意代码的攻击。
在网页中插人一个 applet 就如同在网页中嵌人一幅图片。applet 会成为页面的一部分文本环绕在 applet 占据的空间周围。关键是,这个图片是活动的 (alive)。它会对用户命令做出响应,改变外观,在显示它的计算机和提供它的计算机之间交换数据。
上图展示了Jmol applet,它会显示分子结构。可以利用鼠标旋转和放大各个分子,从而更好地理解分子结构。在发明 applet 的时代,用网页是无法实现这种直接的操作的,那时只有基本的 JavaScript 而没有 HTML 画布。
applet 首次出现时,人们欣喜若狂。许多人相信 applet 的魅力会让 Java 迅速流行起来。然而,初期的兴奋很快就变成了沮丧。不同版本的 Netscape 与 Interet Explorer 运行不同版本的Java,其中有些早已过时。这种糟糕的情况导致更加难以利用Java 的最新版本开发applet。实际上,为了在浏览器中得到动态效果,Adobe 的 Flash 技术变得相当流行。后来Java受到严重安全问题的困扰时,浏览器也放弃了对 applet 的支持。当然,Flash的命运也好不到哪去
略…
版本 | 年份 | 新语言特性 | 类与接口数量 |
---|---|---|---|
1.0 | 1996 | 语言本身 | 211 |
1.1 | 1997 | 内部类 | 477 |
1.2 | 1998 | strictfp 修饰符 | 1524 |
1.3 | 2000 | 无 | 1840 |
1.4 | 2002 | 断言 | 2723 |
5.0 | 2004 | 泛型类、“for each”循环、可变参数、自动装箱、元数据、枚举、静态导人 | 3279 |
6 | 2006 | 无 | 3797 |
7 | 2011 | 基于字符串的Switch 语句、菱形运算符、二进制字面量、异常处理增强 | 4024 |
8 | 2014 | Lambda 表达式、包含默认方法的接口、流和日期/时间库 | 4240 |
9 | 2017 | 模块、其他的语言和类库增强 | 6005 |
11 | 2018 | 局部变量类型推导 ( var)HTTP 客户端、移除Java FX、JNLP、Java EE 重叠模块和CORBA | 4410 |
17 | 2021 | Switch 表达式,文本块、instanceof 模式匹配、记录、密封类 | 4859 |
1.Java是HTML 的扩展。
Java 是一种程序设计语言,HTML 是一种描述网页结构的方式。除了用于在网页上放置Java applet的HTML扩展之外,两者没有任何共同之处。
2.我使用XML,所以不需要 Java。
Java 是一种程序设计语言,XML是一种描述数据的方式。可以使用任何一种程序设计语言处理XML数据,而Java API对XML处理提供了很好的支持。此外,许多重要的XMI工具都是用 Java 实现的。
3.Java 是一种非常容易学习的程序设计语言。
像 Java 这种功能强大的语言大多都不太容易学习。首先,必须将编写玩具式程序的轻松与开发实际项目的艰难区分开来。另外,需要注意的是:本书只用了 7章讨论 Java 语言,其余几章和卷I都在介绍如何使用 Java 类库来具体应用Java 语言。Java类库包含数千个类和接口,还有数万个函数。好在,你不需要知道其中的每一个类或函数,不过,要想用Java解决实际问题,还是需要了解不少内容的。
4.Java 将成为适用于所有平台的通用编程语言。
从理论上讲,这是完全有可能的。但在实际中,某些领域其他语言有更出色的表现,比如,Objective C 和后来的 Swift 在 ios 设备上就有着无可取代的地位。浏览器中的处理几乎完全由 JavaScript掌控。Windows 程序通常都用 C++或C# 编写。Java 在服务器端编程和跨平台客户端应用领域则很有优势。
5.Java 只不过是另外一种程序设计语言。
Java 是一种很好的程序设计语言,很多程序设计人员喜欢Java 胜过 C、C++ 和C#。有几百种很好的程序设计语言没有广泛流行,而有明显缺陷的语言(如 C++ 和 Visual Basic)却大行其道。
这是为什么呢?程序设计语言的成功更多地取决于其支持系统 (support system)的能力,而不是语法的精巧性。人们主要关注的是: 是否提供了有用、便捷和标准的库来实现所需要的特性?是否有工具开发商建立了强大的编和调试环境?语言和工具集是否与计算基础架构的其他部分有效整合?Java的成功缘于其类库能够让人们轻松地完成原本有一定难度的工作,例如网络连接、Web 应用和并发。Java 减少了指针错误,这是一个额外的好处,因此使用 Java 编程的效率更高。但这些并不是 Java 成功的全部原因。
6.Java 是专用的,应该避免使用。
最初创建 Java 时,Sun 公司为发布者和最终用户提供了免费许可。尽管 Sun 公司对 Java拥有最终的控制权,不过在语言版本的不断发展和新库的设计过程中还涉及很多其他公司虚拟机和类库的源代码可以免费获得,不过仅限于查看,而不能修改和再发布。Java 是“闭源的,不过可以很好地使用”。
这种状况在 2007 年发生了巨大变化,Sun 公司官布 Java 未来的版本将在 General PublicLicense(GPL)下发布 (Linux 也使用同样的开放源代码许)。Oracle 公司一直致力于保持Java 开源。目前有多个开源 Java 实现提供商,分别提供不同级别的承诺和支持。
7.Java 是解释性的,因此对于关键应用速度太慢了。
早期的 Java 确实是解释性的。现在 Java 虚拟机使用了即时编译器,因此用 Java 编写的“热点”代码运行速度与 C++ 相差无几,有些情况下甚至更快。
8.所有的 Java 程序都在网页中运行。
有一段时间,Java applet 在 Web 浏览器中运行。如今,Java 程序是运行在 Web 浏览器之外的独立应用。实际上,大多数 Java 程序都在服务器上运行,为网页生成代码或者计算业务逻辑。
9.Java 程序存在重大安全风险。
对于早期的 Java,有过关于 Java 安全系统失效的报道,曾经引起过公众关注。研究人员努力找出 Java 的漏洞,并质疑 applet 安全模型的强度和复杂度,将这视为一种挑战。人们很快就解决了所发现的技术问题。后来又发现了更严重的漏洞,而 Sun 公司以及后来的 Oracle公司反应却很迟缓。浏览器制造商禁用了 Java applet 支持。促成applet 的安全管理器体系结构现在已经过时。如今,Java 应用与其他应用同样安全。由于虚拟机提供的保护,Java 应用比用C或 C++ 编写的应用要安全得多。
10.JavaScript 是 Java 的简易版。
JavaScript 是一种可以在网页中使用的脚本语言,它由 Netscape 发明,最初的名字是LiveScript。JavaScript 的语法让人想到 Java,因为名字也有些相像,但除此之外,两者并无任何关系。尤其是,Java 是强类型的,编译器能捕获类型滥用导致的很多错误。而在JavaScript 中,只有当序运行时才能发现这些错误,所以消除错误要费劲得多。
11.使用 Java 时,可以用廉价的“Internet 设备”取代桌面计算机。
Java 刚刚发布的时候,一些人打赌这肯定会发生。一些公司已经生产出支持 Java 的网络计算机原型,不过用户还不打算放弃功能强大且方便的桌面计算机,而去使用没有本地存储而且功能有限的网络计算机。当然,如今世界已经发生改变,对于大多数最终用户,常用的平台往往是手机或平板电脑。这些设备大多使用Android (安卓)平台。学习 Java 编程对Android 编程也很有帮助。
▲安装Java开发工具包
▲使用命令行工具
▲使用集成开发环境
▲JShell
原先,Oracle 公司会提供最新、最完备的 Java 开发工具包(JDK)版本。如今,很多不同公司(包括 Microsoft、Amazon、Red Hat 和Azul)都提供了最新的 OpenJDK 构建版本,有些公司的许可条件比 Oracle 公司更宽松。网站 https://adoptiumnet,这个网站由开发商、开发人员和用户组共同组成的一个社区运营,为 Linux、Mac OS和Windows 提供了免费的构建版本。
可以从 https://adoptium.net 下载 Java开发工具包,也可以从Oracle 公司网站.www.oracle.com/technetwork/java/javase/downloads 或其他提供商下载。要使用Java SE 17 (LTS)JDK.
术语名 | 缩写 | 解释 |
---|---|---|
Java Development Kit (Java 开发工具包) | JDK | 编写Java程序的程序员使用的软件 |
Java Runtime Environment (Java运行时环境) | JRE | 用来运行Java程序的软件,不带开发工具。(高版本的JDK已经自带JRE,无需单独安装) |
Standard Edition(标准版) | SE | 用于桌面或简单服务器应用的Java平台 |
Micro Edition(微型版) | ME | 用于小型设备的Java平台 |
OpenJDK | – | JavaSE的一个免费开源的实现 |
Hotspot | – | Oracle 开发的“即时”编译器。如果要你选择,请选择这个选项 |
OpenJ9 | – | IBM开发的另一个“即时”编译器 |
Long Term Support (长期支持版本) | LTS | 很多年都支持的一个版本,这不同于每 6个月发布的那些展示新特性的版本。要选择最新的 LTS 版本 |
最好不要接受默认位置(这个路径名中有空格),建议将开发相关的软件放到一个文件夹下
配置环境变量:
右键[此电脑]->属性->高级系统设置->环境变量->在系统变量处,点击新建
变量名为JAVA_HOME
,变量值为E:\kaifa\JDK
【这里的路径为安装JDK的路径】,然后点击确定
在系统变量中找到Path,双击,打开后在右边点击新建,输入%JAVA_HOME%\bin
验证环境变量是否配置成功:Win+R 输入cmd,在里面输入java -version
【空格不要忘了】,回车后如果显示版本号则环境变量配置成功。
下载API文档:Java Development Kit 17 Documentation (oracle.com)
下载解压后,里面的index就是API文档,不过是英文的
这里提供一个中文的API文档【中文API】,版本比较老,但是作为初学者使用应该已经够了
在线中文API文档查看(JDK11):Overview (Java SE 11 & JDK 11 ) (runoob.com)
如果以前有过使用 Microsoft Visual Studio 等开发环境编程的经验,你可能会习惯于开发系统有一个内置的文本编辑器、用于编译和启动程序的菜单以及一个调试工具。JDK 完全没有这些功能。所有工作都要在终端窗口中通过键人命令来完成。这看起来很麻烦,不过确实是一个基本技能。第一次安装 Java 时,希望在安装开发环境之前先检查 Java 的安装是否正确。另外,通过执行这些基本步骤,可以更好地理解开发环境在后台的工作。不过,掌握了编译和运行 Java 程序的基本步骤之后,你可能就会希望使用专业的开发环境。
此处简略介绍
javac 文件名.java
java 文件名
如果只有一个Java文件,可以直接使用java 文件名.java
上一节中,你已经了解了如何从命令行编译和运行一个 Java 程序。这是一个很有用的排错技能,不过对于大多数日常工作来说,还是应当使用集成开发环境。这些环境非常强大也很方便,不使用这些集成开发环境简直有些不合情理。我们可以免费得到一些很棒的开发环境,如 Eclipse、IntelliJ IDEA 和 NetBeans。
这里推荐使用idea,学生可以直接免费使用
Java9引入了另一种使用Java的方法。JShell程序提供了一个“读取 - 评估 -打印循环”( Read-Evaluate-Print Loop,REPL)。键人一个Java 表达式,JShell 会评估输人,打印结果,并等待下一个输人。
要启动JShel1,只需要在终端窗口中键入jshell。JShell 首先显示一个问候语,后面是一个提示符:
现在键人一个表达式,如下:
"Core Java".length()
JShell 会回应一个结果-在这里就是字符串“Core Java”中的字符个数。
$1==>9
注意,你并没有键人 System.out.println。JShell 会自动打印你输入的每一个表达式的值。
输出中的$1 表示这个结果可以用于进一步的计算。例如,如果你键人:
5*$1-3
就会得到:
$2 =-> 42
如果需要多次使用一个变量,可以给它指定一个容易记忆的名字。一定要遵循 Java 语法,指定类型,然后指定变量名。例如,
int answer = 6 * 7
//得到
answer ==> 42
另一个有用的特性是“tab 补全”。
如果键入:Math.
然后再按一次 Tab 键。
你会得到用 Math.类调用的所有方法的一个列表
现在键入l,然后再按一次Tab键。方法名会补全为log,现在你会得到一个比较小的列表:
jshell> Math.l
log( log10( log1p(
jshell> Math.log
接下来你可以手动填入其余代码:
jshell> Math.log10(0.001)
$3 ==> -3.0
要重复运行一个命令,可以连续按↑键,直到看到想要重新运行或编辑的命令行。可以用←和→键移动命令行中的光标位置,然后增加或删除字符。编辑完命令后再按回车键。例如,把命令行中的 0.001替换为 1000,然后按回车键:
jshell> Math.log10(1000)
$5 ==> 3.0
IShell会让Java语言和类库的学习变得轻松而有趣,它不要求你启动一个庞大的开发环境,不会让你再为 public static void main 而困扰。