1996 年 Java 第一次发布就引起了人们的极大兴趣。关注 Java 的人士不仅限于计算机出版界,还有诸如《纽约时报》《华盛顿邮报》《商业周刊》这样的主流媒体。Java 是第一种也是唯一一种在 National Public Radio 上占用了 10 分钟时间来进行介绍的程序设计语言,并且还得到了 $100 000 000 的风险投资基金。这些基金全部用来支持用这种特别的计算机语言开发的产品。重温那些令人兴奋的日子是很有意思的。本章将简要地介绍一下 Java 语言的发展历史。
本书的第 1 版是这样描写 Java 的:“ 作为一种计算机语言, Java 的广告词确实有点夸大其辞。然而, Java 的确是一种优秀的程序设计语言。作为一个名副其实的程序设计人员,使 用 Java 无疑是一个好的选择。有人认为:Java 将有望成为一种最优秀的程序设计语言,但还需要一个相当长的发展时期。一旦一种语言应用于某个领域,与现存代码的相容性问题就摆在了人们的面前。”
我们的编辑手中有许多这样的广告词。这是 Sim 公司高层的某位不愿透露姓名的人士提供的(Sun 是原先开发 Java 的公司)。Java 有许多非常优秀的语言特性, 本章稍后将会详细地讨论这些特性。由于相容性这个严峻的问题确实存在于现实中,所以,或多或少地还是有一些累赘被加到语言中,这就导致 Java 并不如想象中的那么完美无瑕。
但是,正像我们在第 1 版中已经指出的那样,Java 并不只是一种语言。在此之前出现的那么多种语言也没有能够引起那么大的轰动。Java 是一个完整的平台,有一个庞大的库,其中包含了很多可重用的代码和一个提供诸如安全性、 跨操作系统的可移植性以及自动垃圾收集等服务的执行环境。
作为一名程序设计人员,常常希望能够有一种语言,它具有令人赏心悦目的语法和易于理解的语义(C++ 不是这样的)。与许多其他的优秀语言一样,Java 完全满足了这些要求。有些语言提供了可移植性、 垃圾收集等, 但是, 没有提供一个大型的库。如果想要有奇特的绘图功能、 网络连接功能和数据库存取功能就必须自己动手编写代码。Java 具备所有这些特性,它是一种功能齐全的出色语言,是一个高质量的执行环境, 还提供了一个庞大的库。正是因为它集多种优势于一身,所以对广大的程序设计人员有着不可抗拒的吸引力。
Java 的设计者已经编写了颇有影响力的“ 白皮书”,用来解释设计的初衷以及完成的情况,并且发布了一个简短的摘要, 这个摘要用下面 11 个关键术语进行组织:
1 ) 简单性
2 ) 面向对象
3 ) 分布式
4 ) 健壮性
5 ) 安全性
6 ) 体系结构中立
7 ) 可移植性
8 ) 解释型
9 ) 高性能
10 ) 多线程
11 ) 动态性
本节将提供一个小结,给出白皮书中相关的说明,这是 Java 设计者对各个关键术语的论述, 另外还会根据我们对 Java 当前版本的使用经验, 给出对这些术语的理解。
注释: 写这本书时,白皮书可以在 www.oracle.com/technetworic/java/langenv-140151.html 上找到。对于 11 个关键术语的论述请参看 http://horstmann.com/corejava/java-aiw)verview/7Gosling.pdf。
人们希望构建一个无须深奥的专业训练就可以进行编程的系统, 并且要符合当今的标准惯例。 因此,尽管人们发现 C++ 不太适用, 但在设计 Java 的时候还是尽可能地接近 C++, 以便系统更易于理解 , Java 剔除了 C++ 中许多很少使用、 难以理解、 易混淆的特性.:, 在目前看来, 这些特性带来的麻烦远远多于其带来的好处3的确, Java 语法是 C++ 语法的一个“ 纯净” 版本。这里没有头文件、 指针运算(甚至指针语法、) 结构、 联合、 操作符重载、 虚基类等(请参阅本书各个章节给出的 C++ 注释, 其中比较详细地解释了 Java 与 C++ 之间的区别)。然而,设计者并没有试图清除 C++ 中所有不适当的特性。例如, switch 语句的语法在 Java 中就没有改变。如果你了解 C++ 就会发现可以轻而易举地转换到 Java语法
Java 发布时,实际上 C++ 并不是最常用的程序设计语言。很多开发人员都在使用 VisualBasic 和它的拖放式编程环境。 这些开发人员并不觉得 Java 简单。很多年之后 Java 开发环境才迎头赶上如今,Java 开发环境已经远远超出大多数其他编程语言的开发环境简单的另一个方面是小。Java 的目标之一是支持开发能够在小型机器上独立运行的软件。 基本的解释器以及类支持大约仅为 40KB ; 再加上基础的标准类库和对线程的支持(基本上是一个自包含的微内核) 大约需要增加 175KB,
在当时,这是一个了不起的成就。当然,由于不断的扩展,类库已经相当庞大了。现在有一个独立的具有较小类库的 Java 微型版(Java Micro Edition), 这个版本适用于嵌人式设备。
简单地讲, 面向对象设计是一种程序设计技术。 它将重点放在教椐 ( 即对象)和对象的接口上。用木匠打一个比方, 一个“ 面向对象的” 木匠始终关注的是所制作的椅子, 第二位才是所使用的工具;一个“ 非面向对象的” 木匠首先考虑的是所用的工具。在本质上,Java 的面向对象能力与 C++是一样的。
开发 Java 时面向对象技术已经相当成熟。 Java 的面向对象特性与 C++ 旗鼓相当。Java与 C++ 的主要不同点在于多重继承,在 Java 中,取而代之的是更简单的接口概念。与 C++
相比,Java 提供了更丰富的运行时自省功能(有关这部分内容将在第 5 章中讨论 )
Java 有一个丰富的例程库,用于处理像 HTTP 和 FIT 之类的 TCP/IP 协议。Java 应用程序能够通过 URL 打开和访问网络上的对象,其便捷程度就好像访问本地文件一样。
如今,这一点已经得到认可,不过在 1995 年, 主要还是从 C++ 或 Visual Basic 程序连接Web 服务器。
Java 的设计目标之一在于使得 Java 编写的程序具有多方面的可靠性.:, Java 投入了大量的精力进行早期的问题检测、 后期动态的 (运行时)检测,并消除了容易出错的情况… … Java 和 C++ 最大的不同在于 Java 采用的指针模型可以消除重写内存和损坏数据的可能性。
Java 编译器能够检测许多在其他语言中仅在运行时才能够检测出来的问题。 至于第二点,对于曾经花费几个小时来检查由于指针 bug 而引起内存冲突的人来说, 一定很喜欢 Java的这一特性。
Java 适用于网络 / 分布式环境。 为了达到这个目标,在安全方面投入了很大精力。使用 Java 可以构建防病毒、 防篡改的系统。
从一开始,Java 就设计成能够防范各种攻击,其中包括:
原先,Java 对下载代码的态度是“ 尽管来吧!”。不可信代码在一个沙箱环境中执行,在这里它不会影响主系统。用户可以确信不会发生不好的事情, 因为 Java 代码不论来自哪里,都不能脱离沙箱。
不过,Java 的安全模型很复杂。Java 开发包( Java Development Kit, JDK) 的第一版发布之后不久,普林斯顿大学的一些安全专家就发现一些小 bug 会允许不可信的代码攻击主系统。
最初,安全 bug 可以快速修复。遗憾的是,经过一段时间之后, 黑客已经很擅长找出安全体系结构实现中的小漏洞。Sun 以及之后的 Oracle 为修复 bug 度过了一段很是艰难的曰子。
遭遇多次高调攻击之后, 浏览器开发商和 Oracle 都越来越谨慎 _ Java 浏览器插件不再信任远程代码,除非代码有数字签名而且用户同意执行这个代码。
注释: 现在看来, 尽管 Java 安全模型没有原先预想的那么成功, 但 Java 在那个时代确实相当超前。微软提供了一种与之竞争的代码传输机制,其安全性完全依赖于数字签名显然这是不够的, 因为微软自身产品的任何用户都可以证实, 知名开发商的程序确实会崩溃并对系统产生危害
编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码, 只要有Java 运行时系统, 这些编译后的代码可以在许多处理器上运行。Java 编译器通过生成与特定的计算机体系结构无关的字节码指令来实现这一特性。 精心设计的字节码不仅
可以很容易地在任何机器上解释执行,而且还可以动态地翻译成本地机器代码当时, 为“ 虚拟机” 生成代码并不是一个新思路。 诸如 Lisp、 Smalltalk 和 Pascal 等编程语言多年前就已经采用了这种技术。
当然, 解释虚拟机指令肯定会比全速运行机器指令慢很多。 然而, 虚拟机有一个选项,可以将执行最频繁的字节码序列翻译成机器码,这一过程被称为即时编译Java 虚拟机还有一些其他的优点。它可以检测指令序列的行为, 从而增强其安全性。
与 C 和 C++ 不同,Java 规范中没有“ 依赖具体实现” 的地方基本教据类型的大小以及有关运算都做了明确的说明 u例如,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 字节码。由于链接是一个增量式且轻量级的过程, 所以, 开发过程也变得更加快捷,更加具有探索性。这看上去很不错。用过 Lisp、Smalltalk、Visual Basic、Python、R 或 Scala 的人都知道“ 快
捷而且具有探索性” 的开发过程是怎样的。你可以做些尝试, 然后就能立即看到结果。Java开发环境并没有将重点放在这种体验上。
尽管对解释后的字节码性能已经比较满意,但在有些场合下还需要更加高效的性能。字节码可以(在运行时刻)动态地翻译成对应运行这个应用的特定 CPU 的机器码。
使用 Java 的头几年,许多用户不同意这样的看法:性能就是“ 适用性更强”。然而,现在的即时编译器已经非常出色, 以至于成了传统编译器的竞争对手。在某些情况下,甚至超越了传统编译器, 原因是它们含有更多的可用信息。例如, 即时编译器可以监控经常执行哪些代码并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“ 内联”)。即时编译器知道哪些类已经加载= 基于当前加载的类集, 如果特定的函数不会被覆盖,就可以使用内联。必要时,还可以撤销优化。
多线程可以带来更好的交互响应和实时行为。
如今,我们非常关注并发性,因为摩尔定律行将完结。我们不再追求更快的处理器,而是着眼于获得更多的处理器,而且要让它们一直保持工作。不过,可以看到,大多数编程语言对于这个问题并没有显示出足够的重视。
Java 在当时很超前。它是第一个支持并发程序设计的主流语言。从白皮书中可以看到,它的出发点稍有些不同。当时, 多核处理器还很神秘, 而 Web 编程才刚刚起步,处理器要花很长时间等待服务器响应, 需要并发程序设计来确保用户界面不会“ 冻住”。
并发程序设计绝非易事,不过 Java 在这方面表现很出色, 可以很好地管理这个工作。
从各种角度看, Java 与 C 或 C++ 相比更加具有动态性。它能够适应不断发展的环境库中可以自由地添加新方法和实例变量, 而对客户端却没有任何影响。在Java 中找出运行时类型信息十分简单。
当需要将某些代码添加到正在运行的程序中时, 动态性将是一个非常重要的特性。一个很好的例子是: 从 Internet 下载代码,然后在浏览器上运行。如果使用 C 或 C++, 这确实难度很大,不过 Java 设计者很清楚动态语言可以很容易地实现运行程序的演进。最终,他们将这一特性引入这个主流程序设计语言中。
注释:Java 成功地推出后不久, 微软就发布了一个叫做 J++ 的产品, 它与 Java 有几乎相同的编程语言以及虚拟机现在,微软不再支持 J++, 取而代之的是另一种名为 C# 的语言。C# 与 Java 有很多相似之处, 然而使用的却是完全不同的虚拟机、, 本书不准备介绍C++ 或 C# 语言,