logo资料库

JAVA教程(清华).doc

第1页 / 共159页
第2页 / 共159页
第3页 / 共159页
第4页 / 共159页
第5页 / 共159页
第6页 / 共159页
第7页 / 共159页
第8页 / 共159页
资料共159页,剩余部分请下载后查看
JAVA 教程 ————许斌 清华大学计算机系&清华同方股份有限公司 第一讲 Java 语言概述 1 Java 语言的发展史 1.1.1Java 语言在互联网时代获得巨大成功 大家想一想,在 PC 下用 windows 编写的程序能够不做修改就直接拿到 UNIX 系统上运 行吗?显然是不可以的,因为程序的执行最终必须转换成为计算机硬件的机器指令来执行, 专门为某种计算机硬件和操作系统编写的程序是不能够直接放到另外的计算机硬件上执行 的,至少要做移植工作。要想让程序能够在不同的计算机上能够运行,就要求程序设计语言 是能够跨越各种软件和硬件平台的,而 Java 满足了这一需求。 1995 年,美国 Sun Microsystems 公司正式向 IT 业界推出了 java 语言,该语言具有安全、 跨平台、面向对象、简单、适用于网络等显著特点,当时以 web 为主要形式的互联网正在 迅猛发展,java 语言的出现迅速引起所有程序员和软件公司的极大关注,程序员们纷纷尝试 用 java 语言编写网络应用程序,并利用网络把程序发布到世界各地进行运行。包括 IBM、O racle、微软、Netscape、Apple、SGI 等大公司纷纷与 Sun Microsystems 公司签订合同,授 权使用 java 平台技术。微软公司总裁比尔盖茨先生在经过研究后认为"java 语言是长时间以 来最卓越的程序设计语言"。目前,java 语言已经成为最流行的网络编程语言,截止到 2001 年中,全世界大约有 310 万 java 程序员,许多大学纷纷开设 java 课程,Java 正逐步成为世 界上程序员最多的编程语言。 在经历了以大型机为代表的集中计算模式和以 PC 机为代表的分散计算模式之后,互联 网的出现使得计算模式进入了网络计算时代。网络计算模式的一个特点是计算机是异构的, 即计算机的类型和操作系统是不一样的,例如 SUN 工作站的硬件是 SPARC 体系,软件是 U NIX 中的 Solaris 操作系统,而 PC 机的硬件是 INTEL 体系,操作系统是 windows 或者是 Li nux,因此相应的编程语言基本上只是适用于单机系统,例如 COBOL、FORTRAN、C、C ++等等;网络计算模式的另一个特点是代码可以通过网络在各种计算机上进行迁移,这就 迫切需要一种跨平台的编程语言,使得用它编写的程序能够在网络中的各种计算机上能够正 常运行,java 就是在这种需求下应运而生的。正是因为 Java 语言符合了互联网时代的发展 要求,才使它获得了巨大的成功。 1.1.2 Java 语言的产生 任何事物的产生既有必然的原因也有偶然的因素,Java 语言的出现也验证了这一点。1 991 年,美国 Sun Microsystems 公司的某个研究小组为了能够在消费电子产品上开发应用程 序,积极寻找合适的编程语言。消费电子产品种类繁多,包括 PDA、机顶盒、手机等等, 即使是同一类消费电子产品所采用的处理芯片和操作系统也不相同,也存在着跨平台的问 题。当时最流行的编程语言是 C 和 C++语言,Sun 公司的研究人员就考虑是否可以采用 C ++语言来编写消费电子产品的应用程序,但是研究表明,对于消费电子产品而言 C++语 言过于复杂和庞大,并不适用,安全性也并不令人满意。于是,Bill Joy 先生领导的研究小
组就着手设计和开发出一种语言,称之为 Oak。该语言采用了许多 C 语言的语法,提高了 安全性,并且是面向对象的语言,但是 Oak 语言在商业上并未获得成功。时间转到了 1995 年,互联网在世界上蓬勃发展,Sun 公司发现 Oak 语言所具有的跨平台、面向对象、安全性 高等特点非常符合互联网的需要,于是改进了该语言的设计,要达到如下几个目标: ◇ 创建一种面向对象的程序设计语言,而不是面向过程的语言; ◇ 提供一个解释执行的程序运行环境,是程序代码独立于平台; ◇ 吸收 C 和 C++的优点,使程序员容易掌握; ◇ 去掉 C 和 C++中影响程序健壮性的部分,使程序更安全,例如指针、内存申请 和释放; ◇ 实现多线程,使得程序能够同时执行多个任务; ◇ 提供动态下载程序代码的机制; ◇ 提供代码校验机制以保证安全性; 最终,Sun 公司给该语言取名为 Java 语言,造就了一代成功的编程语。 1.2 Java 的工作原理 1.2.1 Java 虚拟机(1) java 虚拟机是软件模拟的计算机,可以在任何处理器上(无论是在计算机中还是在其它 电子设备中)安全并且兼容的执行保存在.class 文件中的字节码。java 虚拟机的"机器码"保 存在.class 文件中,有时也可以称之为字节码文件。java 程序的跨平台主要是指字节码文件 可以在任何具有 java 虚拟机的计算机或者电子设备上运行,java 虚拟机中的 java 解释器负 责将字节码文件解释成为特定的机器码进行运行。java 源程序需要通过编译器编译成为.clas s 文件(字节码文件),Java 程序的编译和执行过程 ——如图所示—— 1.2.1 Java 虚拟机(2) 但是,java 虚拟机的建立需要针对不同的软硬件平台做专门的实现,既要考虑处理器的 型号,也要考虑操作系统的种类。如下图所示,目前在 SPARC 结构、X86 结构、MIPS 和 P PC 等嵌入式处理芯片上、在 UNIX、Linux、windows 和部分实时操作系统上都有 Java 虚拟 机的实现。 ——如图所示—— 1.2.2 无用内存自动回收机制 在程序的执行过程中,部分内存在使用过后就处于废弃状态,如果不及时进行无用内存 的回收,就会导致内存泄漏,进而导致系统崩溃。在 C++语言中是由程序员进行内存回收 的,程序员需要在编写程序的时候把不再使用的对象内存释放掉;但是这种人为的管理内存 释放的方法却往往由于程序员的疏忽而致使内存无法回收,同时也增加了程序员的工作量。 而在 Java 运行环境中,始终存在着一个系统级的线程,专门跟踪内存的使用情况,定期检 测出不再使用的内存,并进行自动回收,避免了内存的泄露,也减轻了程序员的工作量。 1.2.3 代码安全性检查机制 安全和方便总是相对矛盾的。java 编程语言的出现使得客户端机器可以方便的从网络上
下载 java 程序到本机上运行,但是如何保证该 java 程序不携带病毒或者不怀有其它险恶目 的呢?如果 java 语言不能保证执行的安全性,那么它就不可能存活到今天。虽然有时候少 数程序员会抱怨说 applet 连文件系统也不能访问,但是正是各种安全措施的实行才确保了 J ava 语言的生存 字节码的执行需要经过三个步骤,首先由类装载器(class loader)负责把类文件(.clas s 文件)加载到 java 虚拟机中,在此过程需要检验该类文件是否符合类文件规范;其次字节 码校验器(bytecode verifier)检查该类文件的代码中是否存在着某些非法操作,例如 applet 程序中写本机文件系统的操作;如果字节码校验器检验通过,由 java 解释器负责把该类文 件解释成为机器码进行执行。java 虚拟机采用的是"沙箱"运行模式,即把 Java 程序的代码和 数据都限制在一定内存空间里执行,不允许程序访问该内存空间外的内存,如果是 applet 程序,还不允许访问客户端机器的文件系统。 1.2.4 Java 语言的特点(1) 1. 简单、面向对象和为人所熟悉 java 的简单首先体现在精简的系统上,力图用最小的系统实现足够多的功能;对硬件的 要求不高,在小型的计算机上便可以良好的运行。和所有的新一代的程序设计语言一样,j ava 也采用了面向对象技术并更加彻底,所有的 java 程序和 applet 程序均是对象,封装性实 现了模块化和信息隐藏,继承性实现了代码的复用,用户可以建立自己的类库。而且 java 采用的是相对简单的面向对象技术,去掉了运算符重载、多继承的复杂概念,而采用了单一 继承、类强制转换、多线程、引用(非指针)等方式。无用内存自动回收机制也使得程序员 不必费心管理内存,是程序设计更加简单,同时大大减少了出错的可能。java 语言采用了 C 语言中的大部分语法,熟悉 C 语言的程序员会发现 Java 语言在语法上与 C 语言极其相似。 2. 鲁棒并且安全 java 语言在编译及运行程序时,都要进行严格的检查。作为一种强制类型语言,java 在 编译和连接时都进行大量的类型检查,防止不匹配问题的发生。如果引用一个非法类型、或 执行一个非法类型操作,java 将在解释时指出该错误。在 java 程序中不能采用地址计算的 方法通过指针访问内存单元,大大减少了错误发生的可能性;而且 java 的数组并非用指针 实现,这样就可以在检查中避免数组越界的发生。无用内存自动回收机制也增加了 Java 的 鲁棒性。 作为网络语言,java 必须提供足够的安全保障,并且要防止病毒的侵袭。java 在运行应 用程序时,严格检查其访问数据的权限,比如不允许网络上的应用程序修改本地的数据。下 载到用户计算机中的字节代码在其被执行前要经过一个核实工具,一旦字节代码被核实,便 由 java 解释器来执行,该解释器通过阻止对内存的直接访问来进一步提高 java 的安全性。 同时 java 极高的鲁棒性也增强了 Java 的安全性。 3. 结构中立并且可以移植 网络上充满了各种不同类型的机器和操作系统,为使 java 程序能在网络的任何地方运 行,java 编译器编译生成了与体系结构无关的字节码结构文件格式。任何种类的计算机,只 有在其处理器和操作系统上有 java 运行时环境,字节码文件就可以在该计算机上运行。即
使是在单一系统的计算机上,结构中立也有非常大的作用。随着处理器结构的不断发展变化, 程序员不得不编写各种版本的程序以在不同的处理器上运行,这使得开发出能够在所有平台 上工作的软件集合是不可能的。而使用 Java 将使同一版本的应用程序可以运行在所有的平 台上。 体系结构的中立也使得 java 系统具有可移植性。java 运行时系统可以移植到不同的处 理器和操作系统上,java 的编译器是由 java 语言实现的,解释器是由 Java 语言和标准 C 语 言实现的,因此可以较为方便的进行移植工作 2.4 Java 语言的特点(2) 4. 高性能 虽然 java 是解释执行的,但它仍然具有非常高的性能,在一些特定的 CPU 上,java 字 节码可以快速的转换成为机器码进行执行。而且 java 字节码格式的设计就是针对机器码的 转换,实际转换时相当简便,自动的寄存器分配与编译器对字节码的一些优化可使之生成高 质量的代码。随着 java 虚拟机的改进和"即时编译"(just in time)技术的出现使得 Java 的 执行速度有了更大的提高。 5. 解释执行、多线程并且是动态的 如果你了解 C 语言和 C++语言,可以参考下列 Java 与 C/C++语言的比较,如果不了解 C 语言和 C++语言,可以忽略本部分知识。 a. 全局变量 Java 程序不能定义程序的全局变量,而类中的公共、静态变量就相当于这个类的全局变 量。这样就使全局变量封装在类中,保证了安全性,而在 C/C++语言中,由于不加封装的全 局变量往往会由于使用不当而造成系统的崩溃。 b. 条件转移指令 C/C++语言中用 goto 语句实现无条件跳转,而 Java 语言没有 goto 语言,通过例外处理 语句 try、catch、finally 来取代之,提高了程序的可读性,也增强了程序的鲁棒性。 c. 指针 指针是 C/C++语言中最灵活,但也是最容易出错的数据类型。用指针进行内存操作往往 造成不可预知的错误,而且,通过指针对内存地址进行显示类型转换后,可以类的私有成员, 破坏了安全性。在 java 中,程序员不能进行任何指针操作,同时 Java 中的数组是通过类来 实现的,很好的解决了数组越界这一 C/C++语言中不做检查的缺点。 d. 内存管理 在 C 语言中,程序员使用库函数 malloc()和 free()来分配和释放内存,C++语言中则是 运算符 new 和 delete。再次释放已经释放的内存块或者释放未被分配的内存块,会造成系统 的崩溃,而忘记释放不再使用的内存块也会逐渐耗尽系统资源。在 Java 中,所有的数据结 构都是对象,通过运算符 new 分配内存并得到对象的使用权。无用内存回收机制保证了系 统资源的完整,避免了内存管理不周而引起的系统崩溃。
e. 数据类型的一致性 在 C/C++语言中,不同的平台上,编译器对简单的数据类型如 int、float 等分别分配不 同的字节数。例如:int 在 IBM PC 上为 16 位,在 VAX-11 上就为 32 位,导致了代码数据 的不可移植。在 java 中,对数据类型的位数分配总是固定的,而不管是在任何的计算机平 台上。因此就保证了 Java 数据的平台无关性和可移植性。 f. 类型转换 在 C/C++语言中,可以通过指针进行任意的类型转换,不安全因素大大增加。而在 Jav a 语言中系统要对对象的处理进行严格的相容性检查,防止不安全的转换。 g. 头文件 在 C/C++语言中使用头文件声明类的原型和全局变量及库函数等,在大的系统中,维护 这些头文件是非常困难的。java 不支持头文件,类成员的类型和访问权限都封装在一个类中, 运行时系统对访问进行控制,防止非法的访问。同时,Java 中用 import 语句与其它类进行 通信,以便访问其它类的对象。 h. 结构和联合 C/C++语言中用结构和联合来表示一定的数据结构,但是由于其成员均为公有的,安全 性上存在问题。Java 不支持结构和联合,通过类把数据结构及对该数据的操作都封装在类里 面。 i. 预处理 C/C++语言中有宏定义,而用宏定义实现的代码往往影响程序的可读性,而 Java 不支持 宏定义 为易于实现跨平台性,java 设计成为解释执行,字节码本身包含了许多编译时生成的信 息,使连接过程更加简单。而多线程使应用程序可以同时进行不同的操作,处理不同的事件。 在多线程机制中,不同的线程处理不同的任务,互不干涉,不会由于某一任务处于等待状态 而影响了其它任务的执行,这样就可以容易的实现网络上的实时交互操作。Java 在执行过程 中,可以动态的加载各种类库,这一特点使之非常适合于网络运行,同时也非常有利于软件 的开发,即使是更新类库也不必重新编译使用这一类库的应用程序。 1.2.5 Java 平台-不断扩展的计算平台 java 不仅是编程语言,还是一个开发平台,java 技术给程序员提供了许多工具:编译器、 解释器、文档生成器和文件打包工具等等。同时 java 还是一个程序发布平台,有两种主要 的"发布环境",首先 java 运行时环境(java runtime environment,简称 JRE)包含了完整的 类文件包,其次许多主要的浏览器都提供了 java 解释器和运行时环境。目前 Sun 公司把 jav a 平台划分成 J2EE、J2SE、J2ME 三个平台,针对不同的市场目标和设备进行定位。J2EE 是 Java2 Enterprise Edition,主要目的是为企业计算提供一个应用服务器的运行和开发平台。 J2EE 本身是一个开放的标准,任何软件厂商都可以推出自己的符合 J2EE 标准的产品,使用 户可以有多种选择。IBM、Oracle、BEA、HP 等 29 家已经推出了自己的产品,其中尤以 B EA 公司的 weglogic 产品和 IBM 公司的 websphare 最为著名。J2EE 将逐步发展成为可以与
微软的.NET 战略相对抗的网络计算平台。J2SE 是 Java2 Standard Edition,主要目的是为台 式机和工作站提供一个开发和运行的平台。我们在学习 java 的过程中,主要是采用 J2SE 来 进行开发。J2ME 是 Java2 Micro Edition,主要是面向消费电子产品,为消费电子产品提供 一个 java 的运行平台,使得 java 程序能够在手机、机顶盒、PDA 等产品上运行。上述三个 Java 平台的关系 如图所示 1.3 一切都是对象 1.3.1 面向过程 面向对象的第一个原则是把数据和对该数据的操作都封装在一个类中,在程序设计时要 考虑多个对象及其相互间的关系。有些功能并不一定由一个程序段完全实现,可以让其它对 象来实现,在本例中就由类 Max 完成求最大值的功能。而面向对象的另外一个好处是实现 代码的重复使用,例如其它的程序中如果需要求最大值的功能,只需要通过类 Max 的对象 就可以达到目的。但是如果象面向过程的代码段那样把求最大值的算法都实现在该代码段 中,则无法复用 早期的编程语言如 FORTRAN、C 基本上都是面向过程的语言,其编程的主要思路专注 于算法的实现。例如下面是一个面向过程的求正整数最大值的程序: int maxSoFar=0,price=1; while(price>0){ if (price>maxSoFar) maxSoFar=price; //最大值 maxSoFar 的初始值为 0,price 是输入的值 //循环输入 price 的值 //输入的值 price 大于最大值 maxSoFar //则 maxSoFar 的值为 price 的值 String input=JoptionPane.showInputDialog("Enter the next price"); //继续输入 price price=Double.parseDouble(input); } //把字符串 input 转换成整数 price System.out.println("The maximum is "+maxSoFar); //打印最大值 maxSoFar } 该程序段主要实现了求最大值的算法,但是,如果考虑用面向对象的编程,可以是另外 一种方式: Max max=new Max( ); while(price>0){ //max 是类 Max 的一个对象 max.updateMax(price); //对象 max 调用 updateMax 方法,更新最大值 price=max.getPrice( ); //对象 max 调用 getPrice 获得下一个 price 的值 } System.out.println("The maximum is "+max.getMax( ));//对象 max 调用 getMax 方法获得最大值,并打印出来 1.3.2 面向对象 纯粹的面向对象程序设计方法是这样的:
1. 所有的东西都是对象。可以将对象想象成为一种新型变量,它保存着数据,而且还 可以对自身数据进行操作。例如类 Max 中保留着数据的最大值,同时还有方法 updateMax 根据新加入的 price 值产生最新的最大值,还有 getMax 方法返回数据的最大值。 2. 程序是一大堆对象的组合。通过消息传递,各对象知道自己应该做些什么。如果需 要让对象做些事情,则须向该对象"发送一条消息"。具体来说,可以将消息想象成为一个调 用请求,它调用的是从属于目标对象的一个方法。例如上面面向对象的程序段应该是属于某 个类的,比如说是属于类 Shopping,则 Shopping 中就包含了类 Max 的对象 max,调用方法 updateMax 就相当于 Shopping 对象对 max 对象发出一条指令"updateMax",要求对象 max 重 新计算最大值。 3. 每个对象都有自己的存储空间。可容纳其它对象,或者说通过封装现有的对象,可 以产生新型对象。因此,尽管对象的概念非常简单,但是经过封装以后却可以在程序中达到 任意高的复杂程度。 4. 每个对象都属于某个类。根据语法,每个对象都是某个"类"的一个"实例"。一个类 的最重要的的特征就是"能将什么消息发给它?",也就是类本身有哪些操作。例如 max 是类 Max 的实例。 1.4 构建 Java 程序 1.4.1 第一个 Java application java 程序分为 java application(java 应用程序)和 java applet(java 小应用程序)两种。 下面让我们编写一个 java 应用程序,它能够利用来自 java 标准库的 System 对象的多种方法, 打印出与当前运行的系统有关的资料。其中"//"代表一种注释方式,表示从这个符号开始到 这行结束的所有内容都是注释。在每个程序文件的开头,如果这个文件的代码中用到了系统 所提供的额外的类,就必须放置一个 import 语句。说它是额外的是指一个特殊的类库"java. lang"会自动导入到每个 Java 文件 //这是我们的第一个 java application,该程序保存在文件 Property.Java 中 import Java.util.*; /*下面我们用到了 Date 和 Properties 这两个类,是 属于 Java.util 这个包的;*/ /*而 System 和 Runtime 这两个类,是属于 Java.lang 这个包的。*/ public class Property { //程序员给这个类取名为 Property public static void main(String args[]){ //main 是类的主方法 System.out.println(new Date( )); //在命令行下面打印出日期 Properties p=System.getProperties( ); //获得系统的 Properties 对象 p p.list(System.out); //在命令行下打印出 p 中的各个系统变量的值 System.out.println("--- Memory Usage:"); /*打印一行字符串---Memory Usage*/ Runtime rt=Runtime.getRuntime( ); //获得系统的 Runtime 对象 rt System.out.println("Total Memory= " + rt.totalMemory( ) //打印总内存大小
+" Free Memory = " +rt.freeMemory( )); //打印空闲内存大小 } } 在 java 中,程序都是以类的方式组织的,java 源文件都保存在以 java 为后缀的.java 文 件当中。每个可运行的程序都是一个类文件,或者称之为字节码文件,保存在.class 文件中。 而作为一个 Java application,类中必须包含主方法,程序的执行是从 main 方法开始的,方 法头的格式是确定不变的: public static void main(String args[]) 其中关键字 public 意味着方法可以由外部世界调用。main 方法的参数是一个字符串数 组 args,虽然在本程序中没有用到,但是必须列出来。 程序的第一行非常有意思: System.out.println(new Date()); 打印语句的参数是一个日期对象 Date,而创建 Date 对象的目的就是把它的值发给 print ln()语句。一旦这个语句执行完毕,Date 对象就没用了,而后"无用内存回收器"会将其收回。 第二行中调用了 System.getProperties( )。从帮助文档中可知,getProperties( )是 System 类的一个静态方法(static 方法),由于它是"静态"的,所以不必创建任何对象就可以调用 该方法。在第三行,Properties 对象有一个名为 list( )的方法,它将自己的全部内容都发给一 个 PrintStream 对象,该对象就是 list()方法的参数。 第四行和第六行是典型的打印语句,其中第六行通过运算符"+"的重载来连接多个字符 串对象,在 Java 中只有当"+"运算符作用于字符串时在能够进行重载。但是让我们仔细观 察下述语句: System.out.println("Total Memory= " + rt.totalMemory( ) //打印总内存大小 +" Free Memory = " +rt.freeMemory( )); //打印空闲内存大小 其中,totalMemory( )和 freeMemory( )返回的是数值,并非 String 对象。如果将一个字 符串与一个数值相加,结果会如何?在这种情况下,编译器会自动调用一个 toString()方法, 将该数值(int 型或者 float 型)转换成字符串。经过这样处理以后,就可以用"+"进行字符 串连接了。 main()的第五行通过调用 Runtime 的 getRuntime()方法创建了一个 Runtime 对象,该对 象中包含了内存等信息。 1.4.2 Java 程序的编辑
分享到:
收藏