Java无难事:详解Java编程核心思想与技术
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.5 Java的特性

早在Java诞生之初,Sun公司就发表了一份白皮书,用了一连串的修饰语来定义Java,称Java是简单的、面向对象的、健壮的、安全的、结构中立的、可移植的、高性能的、解释执行的、多线程的、动态的、平台无关的语言。下面就让我们一起看一下Java的这些特性。

1.5.1 简单

Java最初是为了对家用电器进行集成控制而被设计出来的一种语言,因此它必须简单明了。Java语言的简单性主要体现在三个方面:

● 在设计时,Java吸取了C++的一些语法特性,因而C++程序员在初次接触Java语言时,就会对其感到很熟悉。从某种意义上讲,Java语言是C及C++语言的一个变种,因此,C++程序员可以很快地掌握Java编程技术。

● Java摒弃了C++中容易引发程序错误的一些特性,如指针、结构、操作符重载、多重继承等。

● Java提供了丰富的类库。利用Java提供的类库,我们可以快速开发文件读写程序、图形界面程序、网络通信程序等许多应用程序。

1.5.2 面向对象

提到Java,就不得不说它的面向对象的特性。了解C++的人都知道,C++为了向下兼容C语言,因此既支持面向对象,又支持面向过程的开发。而Java则是一个完全面向对象的语言,在Java的世界中,一切都是对象!面向对象的所有核心特性(如封装、继承、多态等),Java都给予了很好的支持。

1.5.3 健壮

Java致力于检查程序在编译和运行时的错误。与C++类似,Java也是一种强类型的语言,不过在类型检查方面,Java比C++还要严格!类型检查可以帮助我们检查出许多在开发早期就出现的错误。

除了类型检查外,Java还引入了垃圾内存回收(GC)机制,这个功能有效地避免了内存泄漏的问题,让程序运行更加稳定。在C和C++中,我们经常会定义一个指针,然后为其动态分配一块堆内存,当我们利用这个指针完成某个功能后,经常忘记释放为这个指针所分配的内存,这样就会造成内存泄漏。在Java语言中,当我们为一个对象分配内存后,不需要去考虑什么时候为这个对象释放内存,所有这一切都由Java的垃圾内存回收机制来完成,它会自动帮助我们回收无用的内存。

1.5.4 安全

Java被设计为用于网络/分布式的环境,这意味着其安全性就格外重要了。Java的安全性可以从两个方面得到保证。一方面,在Java语言里,删除了指针和释放内存等C++功能,避免了非法内存操作;另一方面,通过Java的安全体系架构来确保Java代码的安全性。当我们从网上下载Java代码在本地执行时,Java的安全架构能确保恶意的代码不能随意访问我们本地计算机的资源,例如,删除文件、访问本地网络资源等操作都是被禁止的。

1.5.5 结构中立

Java被设计为支持应用程序部署到各种不同的网络环境中。在这样的环境中,Java应用程序必须能够在各种不同的硬件环境和各种不同的操作系统平台下运行。为了实现这一目标,Java编译器将Java源代码编译成一种结构中立的中间文件格式——字节码(bytecodes)。字节码与特定的计算机体系结构无关,只要有Java运行环境的机器就都能够执行这种中间代码。

1.5.6 可移植

Java所具有的同体系结构无关的特性使得其应用程序可以在配备了Java解释器和运行环境的任何计算机系统上运行,这成为Java应用软件便于移植的良好基础。但仅仅如此还不够,如果基本数据类型设计依赖于具体实现,也将为程序的移植带来很大的不便。例如在Windows 3.1中整数为16位,在Windows 95中整数为32位,在DEC Alpha中整数为64位,在Intel 486中整数为32位。通过定义独立于平台的基本数据类型及其运算,Java数据得以在任何硬件平台上保持一致。Java语言的基本数据类型及其表示方式如下:

● byte——8-bit二进制补码

● short——16-bit二进制补码

● int——32-bit二进制补码

● long——64-bit二进制补码

● float——32-bit IEEE 754浮点数

● double——64-bit IEEE 754浮点数

● char——16-bit Unicode字符

1.5.7 高性能

Java可以在运行时直接将目标代码翻译成机器指令,这主要是由Java虚拟机中的JIT(Just In Time,即时编译)编译器来实现的。随着JIT编译器技术的发展,Java代码的运行速度越来越接近于C++代码。

1.5.8 解释执行

用C++语言编写的程序是通过编译器编译成本地机器指令,然后执行的,这种方式生成的代码指令可以被CPU直接“读懂”。而Java则采用了另外一种方式,Java也有编译器,但是Java编译器是将Java程序编译成字节码,这是一种中间代码。CPU当然是“读不懂”字节码的,因此Java还需要一个翻译来把这个字节码翻译成CPU能“读懂”的机器码,而这个“翻译”就是Java解释器。

1.5.9 平台无关

在上面提到了Java是解释执行的,正因为有了这个前提,Java程序才能在任何机器平台上运行。

对Linux或UNIX操作系统有了解的读者知道,Linux操作系统会针对不同的CPU发布不同的版本。由于Linux系统是使用C语言开发的,而C语言编译器生成的是机器代码,所以,不同类型的CPU只能使用针对该类型CPU编译的Linux版本。

举个例子,中国的民用电压是220V,美国的民用电压是110V,如果把符合中国电压标准的电器直接拿到美国使用,那么由于美国电压太低,电器肯定工作不了,反过来,美国的电器直接在中国使用可能就会被烧坏了。如果在市电与电器中间加入一个智能变压器,这个变压器根据不同的电网规格和电器规格对电压进行调配,那么任何一个电器,在任何一个国家都可以正常工作了,而Java的解释器就类似于这个智能变压器。

由于有了Java解释器,所以只要针对不同CPU开发出不同的Java解释器,那么Java程序就可以在不同的平台下稳定运行了。

1.5.10 多线程

Java语言的另一个重要特性就是在语言级支持多线程的程序设计。线程对有些读者来说可能是一个新名词,那么什么是线程?多线程又能带来什么好处呢?读者可以把一个线程想象为一个人,如果某项工作由1个人(单线程)来做要花费10分钟,那么由5个人(5个线程)来做可能只需要2~3分钟。可以看出,多线程可以提高工作效率。

在C++中,要想使用多线程,我们必须寻找一个第三方的库来实现对线程的操作(如Windows的线程库等),毕竟C++标准并没有与线程相关的定义。但是在Java中,与线程相关的库已经包含在了Java的类库中,而且与线程相关的规范也写入了Java语言的标准当中,这样我们就不用费心去寻找一个线程库了。

提示:C++ 11标准已经引入了对多线程的支持。

1.5.11 动态

Java的动态特性是其面向对象设计方法的扩展,它允许程序动态地装入运行过程中所需要的类,这是我们使用C++语言进行面向对象程序设计所无法实现的。

在C++程序设计过程中,每当在类中增加一个实例变量或一个成员函数后,继承该类的所有子类就都必须重新编译,否则将导致程序崩溃,而Java则采用了一些措施来解决这个问题。

首先,Java编译器不是将对象实例变量和成员函数的引用编译为数值引用,而是将符号引用信息保存在字节码中,传递给解释器,由解释器在完成动态链接类后,将符号引用信息转换为数值偏移量。一个在存储器中生成的对象不在编译过程中决定,而是延迟到运行时由解释器确定。这样,对类中变量和方法进行更新时就不至于影响现有的代码。在解释执行字节码时,这种符号信息的查找和转换过程仅在一个新的名字出现时才进行一次,随后,代码便可以全速运行。在运行时确定引用的好处是可以使用已被更新的类,而不用担心影响其他代码。如果程序链接了网络中另一个系统中的某一个类,该类的所有者也可以自由地对该类进行更新,而不会使任何引用该类的程序崩溃。