Java是一种可以编写跨平台应用软件的面向对象的程序设计语言,它最初是由Sun公司的James Gosling等人于1991年提出设想并开始设计开发的,第1个版本花费了大约18个月的时间,开始起名为Oak,于1995年更名为Java。到目前为止,Java已经成为一种广泛使用的网络编程语言。因为它所编写的程序不但可以保证安全、稳健且和平台无关的通过网络传播,而且更容易编写、管理和维护,代价也更低。
说起来多少有些令人吃惊,Java的最初推动力并不是网络,而是源于对平台无关性的需要。Java的前身主要是作为一种用于小家用电器的编程语言,解决诸如电视机、电话、微波炉等家用电器的控制和通信问题。因为在这种小型家用电器中用作控制器的CPU芯片是多种多样的,当时主流的编程语言C和C++所开发的程序只能一次应用于某一个特定的芯片。尽管可以为所有的CPU芯片编写各自的程序,但是创建适用于各种CPU芯片的编译器是一项非常费时费力的工作。为了找到一种简单而且经济的方案,Sun公司的Gosling 等人便开始一起致力于开发一种可移植、跨平台的语言,该语言能够生成运行于不同环境、不同CPU芯片上的代码。然而,由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。就在Oak语言几乎夭折的时候,Inte.net技术得到了空前的发展,Gosling等人通过和Web技术的对比,看到了Oak语言在计算机网络上的广阔应用前景,于是改造了Oak,并在1995年5月23日正式以“Java”的名称对外发布。同年,Sun公司决定免费向公众发放Java的开发工具包,并和当时著名的网景公司合作,将Java的虚拟机加入到Nescape浏览器当中。这一系列举措都使得Java伴随着Internet的迅猛发展而发展起来,并逐渐成为重要的Internet编程语言。
要想更好地了解Java为什么会如此成功,就必须了解它产生的原因、推动它发展的动力,以及它对其他语言的继承。Java的产生与过去40年中计算机语言的改进和不断发展密切相关。而每一次语言设计的革新都是因为先前的语言不能解决目前遇到的基本问题而引起,Java也不例外。归纳起来,计算机语言的革新和发展需要两个基本因素:第一就是它必须适应正在变化的环境和需求,第二就是它必须能够实现编程艺术的完善与提高。
说到这里,我们不得不提到C语言。20世纪70年代中期,C语言的出现深刻的影响了整个计算机界,并从根本上改变了编程的方法和思路。可以说,C语言是当时人们不断追求结构化、高效率的直接结果。然而程序设计语言的发展在这之前又是怎样的局面呢?主流的编程语言如:汇编语言虽然能够写出高效率的程序,但是不便于学习,而且使用和调试汇编程序也相当困难;BASIC语言虽然容易学习,但功能不够强大,更不用说结构化,这使它根本无法应用到较大的程序中;FORTRAN语言在科学计算应用方面确实可以编写出相当高效的程序,但它不适于编写系统程序。尽管当时人们对编程语言实现结构化的要求非常强烈,然而BASIC和FORTRAN等程序设计语言都没有考虑结构化问题,而是使用GOTO语句作为对程序进行控制的主要方法。这样一来,用这些语言编写的程序往往就成了“意大利面条式的程序代码”,一大堆混乱的跳转语句和条件分支语句使得程序难以理解,并且给调试工作也带来了巨大的困难。Pascal语言正是为缓解这一矛盾而出现的,不过虽然Pascal是结构化语言,但是它的设计效率很低,仍然无法编写系统程序代码。而当时的情况是,早期的计算机语言开发软件的效率和功能已经根本无法满足人们对软件的需求量日益增加的需要。也就是在这个时候,C语言出现了,它功能强大、高效、满足结构化要求、简单易学,而且它的设计、实现、开发是由真正从事编程工作的程序员在考虑了现实编程工作的实际需要后而完成的。它的特性经由实际运用该语言的人们不断去提炼、测试、思考、再思考,使得C语言最终成为程序员们最喜欢使用的程序设计语言。幸运的是,Java也继承了这个思想。
正当C语言成为主流的计算机编程语言的时候,问题又出现了,也就是在20世纪80年代初,随着软件规模的增大,软件设计和开发的复杂性日益突出,对于软件的管理甚至需要依赖于工程学的方法才能够实现。此时,C语言已经显得力不从心。因为,许多工程项目的复杂性都超过了结构化方法的极限。为了对程序的复杂性更好地进行管理,面向对象编程(OOP)方法诞生了,这种方法的核心思想是通过使用继承、封装和多态性来帮助组织复杂的程序。C++是这一时期非常重要的面向对象程序设计语言,它是在C语言的基础之上通过增加面向对象的特性来扩充C语言,因此它包括了C语言的所有特征、属性和优点。这也是C++作为编程语言成功的一个关键因素。因为C++的发明并不是企图创造一种全新的编程语言,而是对一个已经高度成功的编程语言进行改进。正是由于C++既有面向对象的特征,又有C语言高效和格式上的优点,使得它直到现在也是一种可以被广泛应用的编程语言。然而,语言的发展并没有结束,互联网的迅猛发展使得程序设计语言又产生了新的变化,这一变化最终导致了Java的出现。
导致Java出现的根本力量是对程序可移植性的迫切要求。尽管这种要求并不是在互联网出现之后才有的,而是和程序设计语言的出现几乎同步,但是由于各种原因,这种需求并不是那么迫切。然而,随着Internet和Web技术的出现和繁荣,对程序可移植性的要求变得重要且紧迫起来。这是因为,互联网中存在着大量不同的、分布式的系统,这其中包括了各种类型的计算机、操作系统和CPU芯片。人们虽然实现了各种类型的平台都可以和互联网进行连接,共享资源,但是还无法在各种平台上运行同样的程序。因此,可以这么说,中立体系结构编程语言的需要是促使Java诞生的主要动力,而Internet最终导致了Java的成功。
实际上,Java的大部分特性都是从C和C++中继承而来的,这也是Java成功的一个方面。Java的设计人员觉得,在新语言中使用熟悉的C语法及模仿C++面向对象的特性,将使他们的编程语言对经验丰富的C和C++程序员有更大的吸引力。而且,Java的设计和测试工作是由真正从事编程工作的人员完成,它源于设计它的人员的需要和经验,因而也是一种程序员自己的语言。可以说,Java是一种在各方面性能表现都很好的编程语言,它的特点可以表现在以下几个方面。
1 / 简单
Java是一种面向对象的程序设计语言,只要学过C或者C++,那么学习Java也会非常容易,因为Java继承C和C++的语法以及许多C++面向对象的特性。当然,即使没有学过其他程序设计语言,学习Java也不是很难,因为Java的设计目的就是让程序员或者准程序员觉得既易学又好用。Java简单的另一个方面是它摒弃了C++中许多容易出错和混淆的概念,如指针、运算符重载、多重继承等,取而代之的是通过其他更清楚、更易理解的方式来实现。此外,Java还通过实现自动垃圾回收机制而大大简化了程序设计人员对内存的管理工作,减少了错误的发生。
2 / 面向对象
Java语言借鉴了近几十年来所有面向对象程序设计语言的优点。提供了简单的类机制和动态灵活的接口模型,使得开发工作完全集中于对象本身和接口的设计。通过对对象状态以及行为的封装实现了信息的有效隐藏和模块化要求。通过类的继承机制实现了向上对问题域的高度抽象以及向下对程序代码的有效复用。可以说,Java保证了对象模型既简单又容易扩展。
3 / 稳健性与安全性
在设计Java的时候,最优先考虑的就是怎样才能创建出稳健的、安全可靠的程序,这是因为在网络这个多平台的环境中,程序必须得到可靠的执行。为了实现这个目标,Java被设计成一种严格类型检查的语言,它不但在编译时对代码进行检查,而且在运行程序时也会对可能出现的问题进行检查,这样就可以及早地发现错误并进行消除。其实,程序失败的原因无外乎以下两种:内存管理错误和误操作引起的异常情况。
使用C和C++编写的程序虽然效率很高,但是很多复杂的工作都需要程序员自己来实现。比如内存的管理,C和C++的程序员必须手工分配并且释放所有的动态内存,这样做就会导致一些问题,如程序员可能忘记释放原来分配过的内存,或者释放了其他部分程序正在使用的内存。为了从根本上消除这些问题,Java提供了自动垃圾回收机制来帮助程序员管理内存的分配和释放,从而将程序员从复杂、乏味的内存管理工作中解脱出来。
此外,类似于“被零除”、“数组下标越界”或者“文件未找到”这样的误操作也经常在程序中发生。如果程序员在C或者C++中要避免这类问题发生,必须编写一大堆难以理解的指令。而Java完全不必这样去做,它通过集成的面向对象的异常处理机制来对可能出现但未被处理的异常进行提示,从而更好的对运行时错误进行管理以防止系统崩溃。另外,Java在编译时还可以捕获类型声明中的许多常见错误,从而防止动态运行时不匹配问题的出现。
在Java中,限制对指针的使用也是保证程序安全可靠的重要原因之一。Java规定一切对内存的访问都必须通过对象的实例变量来实现,实例变量中的内容其实就是指针,只不过Java不允许程序员对其进行删除和计算,这样一来就可以避免从外部在未授权的情况下访问对象的私有成员,也可以避免由于对指针的错误操作而引起的不必要的麻烦。
下载小应用程序并能确保它对客户机的安全性不会造成危害也是Java安全可靠的一个重要的方面。也就是说,每当使用一个兼容Java的Web浏览器时,你可以安全地下载Java小应用程序。这是因为,Java将小应用程序限制在Java的运行环境中,不允许它访问客户机的其他部分,就像是在网络应用程序和计算机之间提供了一道防火墙,从而不必担心病毒的感染或其他恶意的企图了。
4 / 多线程
Java的设计目标之一是为了满足人们能够在互联网上创建运行平稳的交互式程序的需要,这就要求Java编写的应用程序能够同时执行多个任务。为了更好地管理多任务,Java提供了对多线程编程的内嵌支持。多线程使应用程序能够并行执行,而且同步机制保证了对共享数据的正确操作。通过使用多线程,程序设计人员可以分别用不同的线程完成特定的功能,而不需要采用全局的事件循环机制,这样就能很容易地实现网络上的实时交互功能。而且,多线程还能够最大限度地利用CPU资源。这在用Java操作交互的、网络环境下的应用程序时也显得非常重要。
5 / 体系结构中立和可移植性
程序员面临的一个主要问题是,不能保证今天编写的程序明天能否在同一台机器上顺利运行,更不能保证在这台机器上编写的程序能否在其他机器上顺利运行。这是因为操作系统升级、处理器升级以及核心系统资源的变化,都可能导致程序无法继续运行。Java通过虚拟机的实现来保证Java语言编写的程序对每种计算机都一样的运行。比如,简单的类型都是不变的:整数总是32位,长整数总是64位。令人奇怪的是,诸如C及C++等主流的编程语言却不是这样。由于这些语言定义如此自由,每种编译器及开发环境便各有不同了,这使程序的移植成为非常棘手的问题。Java程序的移植却很容易,而且不需要进行重新编译。这是因为Java能够通过自身的编译器将源程序生成与体系结构无关的字节码指令,只要安装了Java虚拟机,这种字节码指令就可以根据对应于Java虚拟机中的表示,转换成本地的机器码,然后就可以在任意的平台上运行了。
与平台无关的特性使Java程序可以方便地被移植到网络上的不同机器。同时,Java的类库中也实现了与不同平台的接口,使这些类库可以自由地移植。可以这么说,Java真正实现了“一次编译、到处运行”的设计目标,使程序的可移植性从梦想变成了现实。
6 / 解释性和高性能
当运行Java程序时,它首先被编译成字节码,然后通过Java解释器直接对Java字节码进行解释执行。虽然这个过程是解释执行的,但是由于字节码的设计并不专门针对任何一种特定的机器,而是非常类似于机器指令的指令编码。因而通过Java的虚拟机就可以很容易的直接将字节码转换成对应于特定CPU的机器码,从而得到较高的性能。这种转换的效率比其他解释性语言如Basic、Perl等要高得多,甚至在非常低档的CPU上也能顺利运行。不过Java毕竟是解释性的语言,它解释执行的意义在于能够实现程序一经编译便可在众多不同的计算机上执行的跨平台运行。虽然这比C程序慢了许多,但在大多数应用中都是可以接受的。而且,现在Java也已经有了专门的代码生成器,可以很容易使用JIT编译技术将字节码直接转换成高性能的本机代码。值得一提的是,Java运行时系统在提供这个特性的同时仍具有平台独立性,因而“高效且跨平台”对Java来说不再矛盾。
7 / 分布式
能够在Internet的分布式环境中运行Java程序也是Java的设计目标之一。特别是它提供了用于处理TCP/IP协议的专用类库,这样用户就可以通过URl地址存取资源,并且还可以很方便的在网络上访问其他对象。
8 / 动态性
Java从一开始就被设计成动态地、可扩展的面向对象程序设计语言,这一优势可使它适合于一个不断发展的环境。程序员可以在类库中自由地加入新的方法和实例变量而不会影响用户程序的执行。并且Java通过接口来支持多重继承,使之比严格的类继承具有更灵活的方式和扩展性。此外,Java的动态性特征也为小应用程序在运行时可以动态地更新提供了保障。
由于Java和C++之间的相似性,容易使人们将Java简单地想象为“C++的增强版本”。但其实这是一种误解。Java在各个方面都与C++有重要的不同。Java的出现也并不是用来取代C++的,设计Java是为了解决某些特定的问题,而设计C++是为了解决另外一类完全不同的问题。两者将长时间共存。那么Java和C++都有哪些区别呢?下面仅列出一些比较明显的区别:
1 / 数据类型及类
Java是完全面向对象的语言,所有函数和变量必须是类的一部分。除了基本数据类型之外,其余的都作为类对象,包括数组和字符串。对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可拥有自己的属性和行为。而C++允许将函数和变量定义为全局的。此外,Java中取消了C/C++中的结构体和联合,消除了不必要的麻烦。
2 / 类型转换
Java和C/C++都具有自动类型转换的机制,但是在强制类型转换方面,则有所不同。例如,在C++中可以隐含的将浮点数赋予整型变量,通过去掉其尾数来实现。Java则不支持这种自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
3 / 指针
Java语言让程序设计人员无法直接访问和修改指针,而且通过自动内存管理功能有效地防止类似于C/C++语言中对指针的误操作。但是这并不是说Java没有指针,而是这种指针只能供Java虚拟机内部使用,而不能由程序员使用罢了,这些限制都大大增强了Java程序的安全性。
4 / 预处理功能
C/C++在编译过程中都有一个预编译阶段。预处理阶段可以为开发人员提供方便,但增加了编译的复杂性。但是Java不支持预处理功能,Java虚拟机通过提供引入语句(import)来实现和C/C++的预编译功能相似的作用。
5 / 多重继承
C++支持多重继承,它允许一个类继承多个父类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容易。Java为了避免这些问题,取消了对多重继承的支持,为了平衡对语言本身造成的损失,Java通过允许一个类可以实现多个接口的方式来达到类似于C++多重继承的功能。
6 / 自动内存管理
Java程序中所有的对象都是用new操作符建立在内存的堆中,这个操作符类似于C++的new操作符,但是对无用对象的删除方式却是完全不同的。在Java中,当一个对象不再被使用时,不用程序员自己来进行删除,Java会自动进行无用内存回收操作,这个操作是以线程的方式在后台运行的。而C++中必须由程序员自己编写代码来释放内存资源,这显然会增加程序设计人员的负担。
7 / 字符串
在C/C++中不支持字符串变量,Java中虽然有字符串类型,但是是以对象的形式存在的。这样做有许多好处,比如:我们在整个系统中对建立字符串和访问字符串元素的方法时一致的;以类对象的方式存在,可以在程序执行时进行有效的检查,并有助于排除运行时错误的发生;对字符串可以通过“+”进行连接操作,从而便于字符串和非字符串之间的合并。
8 / 异常
Java提供了强大的异常处理机制用于捕获程序运行时错误,但是却不需要程序员编写非常复杂的代码。因为,几乎程序中所有可能遇到的异常都被Java自动地进行处理,我们只需要在可能发生异常的代码前后用try…catch语句声明就可以了,显然这种处理工作增强了系统的容错能力。而C++则没有如此方便的针对异常的处理机制。
9 / 操作符重载
Java不支持操作符重载。操作符重载被认为是C++的突出特征。在Java中,虽然类大体上可以实现这样的功能,但操作符重载的方便性仍然丢失了不少。Java不支持操作符重载是为了保持Java尽可能简单。
无论怎样,Java和C++都是面向对象语言。也就是说,它们都能够实现面向对象的思想(封装、继承和多态)。由于C++为了照顾大量的C语言使用者而兼容了C,使得自身仅仅成为了带类的C语言,多多少少影响了其面向对象的彻底性。Java则是完全的面向对象语言,它语法更清晰,规模更小,更易学。它是在对多种程序设计语言进行了深入细致研究的基础上出现的,不但摒弃了其他语言的不足之处,而且从根本上解决了C++语言中所固有的缺陷。
可以这么说,环境的变化促使Java这种独立于平台的语言注定成为Internet上的分布式编程语言。同时,Java也改变了人们的编程方式,特别是Java对C++使用的面向对象范例进行的增强和完善。所以,Java不是孤立存在的一种语言,而是计算机语言多年来的演变结果。仅这个事实就足以证明Java在计算机语言历史上的地位。Java对Internet编程的影响就如同C语言对系统编程的影响一样,因而有人预言:“Java语言的出现,将会引起一场软件革命”一点也不为过。
回书目 上一节 下一节 |