Board logo

标题: SUN JAVA标准教程 [打印本页]

作者: starlight    时间: 2004-12-1 10:07     标题: SUN JAVA标准教程

关于本课程
本书的主要目标是为你提供有关Java应用和Java applets的面向对象的程序设计所必需的知识和技能;并讲授Java编程语言句法和面向对象的概念,以及Java运行环境的许多特性, 对图形用户界面(GUIs)、多线程和网络的支持等。本课程包括了参加SUN Certified Java Programmer和SUN Certified Java Developer考试所必备的知识。
一、课程概述
   
课程概述
本课程主要包括以下内容:
-Java编程语言句法
-应用于Java编程语言的面向对象的概念
-图形用户界面(GUI)编程
-创建Applet
-多线程
-网络
本课程首先讨论了Java运行环境和Java编程语言句法,然后阐述了应用于Java编程语言的面向对象的概念;随着课程的进展还将讨论有关Java平台的更先进的特性。
本课程授课对象应具备运用Java 编程语言或其它语言进行基本语言设计的能力,它是“非程序员Java编程”(“Java Programming for Non—Programmers”,SL-110)课程的延续。
    尽管Java编程语言独立于操作系统,但它所产生的图形用户界面(GUI)却可能依赖于执行其代码的操作系统。本课程中的例题所使用的代码运行于Solaris TM操作系统,因而本手册中的图形具备Motif GUI。如果将这些代码运行于Windows 95操作系统,则可产生Microsoft Windows 95 GUI。本课程的内容适用于所有Java操作系统端口。
二、课程图
每一模块的课程都从一张课程图开始,使学员可掌握自己的学习进度。全课程设置流程图如下所示:

作者: starlight    时间: 2004-12-1 10:07     标题: SUN JAVA标准教程

三、各模块概述
各模块概述
-模块1──起步
-模块2──标识符、关键字和类型
-模块3──表达式和流程控制
-模块4──数组
-模块5──对象和类
-模块6──高级语言特性
-模块7──异常
-模块8──建立GUIs
-模块9──AWT事件模型
-模块10──AWT组件库
-模块11──Java基础类
-模块12──Java Applets介绍
-模块13──线程
-模块14──流式I/O和文件
-模块15──网络
-模块1──起步
本模块概述了Java编程语言的主要特性及Java应用程序,阐述了类和包的概念,并介绍了一些常用Java包。
-模块2──标识符、关键字和类型
Java编程语言与C语言类似,具有许多编程构造。本模块对这些构造作了一般介绍并讲授了每一构造所要求的一般句法。此外,还介绍了采用集合数据类型进行数据关联的面向对象的方法。
-模块3──表达式和流程控制
本模块介绍了包括运算符和Java程序控制句法在内的表达式。
-模块4──数组
本模块讲解了如何声明、创建、初始化和拷贝Java数组。
-模块5──对象和类
本模块是在模块2的基础上,对Java对象的概念作了进一步的阐述,包括重载、覆盖、子类和构造函数。
-模块6──高级语言特性
本模块是模块5的继续,它进一步讲解了Java面向对象的编程模块,包括一些新的JDK1.1特性──降级和内部类。该模块还介绍了在Java开发包JDKTM 1.2中新增的收集的概念。
-模块7──异常
本模块为Java程序员提供了一种在运行Java程序时俘获错误的机制,并阐述了预定义异常和用户定义异常。
-模块8──建立GUIs
在Java编程语言中,所有图形用户界面都是建立在框架和面板的概念之上。本模块介绍了布局管理和容器的概念。
-模块9──AWT事件模型
Java编程语言1.1版的最重要的变化就是将事件送入和送出Java组件的方法的变化。本模块阐述了JDK1.0和1.1的事件模型的区别,并演示了如何建立小型事件柄(compact event handler)的方法。
-模块10──AWT组件库
本模块介绍了用于建立Java GUIs的抽象窗口工具包(AWT)组件,并演示了Java AWT组件和1.1事件模型共同工作的方法。
模块11──Java基础类介绍
本模块重点介绍了JDK1.2的一个重要特性──Java基础类(JFC),阐述了Swing组件和它们的可插入式外观及感觉的
作者: starlight    时间: 2004-12-1 10:08     标题: SUN JAVA标准教程



体系结构,并介绍了一例基本的Swing应用及JFC的其它特点,例如在二维图形、存取性及拖放(Drag and drop)等方面的应用。
-模块12──Java Applets介绍
本模块演示了applet 和应用程序开发之间的区别,并介绍了JDK 1.2的声音增强功能.
-模块13──线程
线程是一个复杂的论题。本模块阐述了与Java编程语言相关的线程问题,并介绍了一个简单的线程通信和同步传输实例。
-模块14──流式I/O和文件
本模块阐述了既可读写数据又可读写文本文件的类,并介绍了对象流的概念。
-模块15──网络
本模块介绍了Java网络编程包并演示了传输控制协议/Internet协议(TCP/IP)客户──服务器模型。
四、课程目标
完成本课程的学习后,你应该能够:
-  描述语言的主要特性
-  编译并运行Java应用程序
-  理解和使用在线超文本Java技术文件
-  描述语言句法元素和构造
-  理解面向对象的例子并使用该语言的面向对象特性
-  理解并使用异常
-  开发图形用户界面
-  描述Java技术平台上的用于建立GUIs的抽象窗口工具包
-  从GUI输入
-  理解事件处理
-  描述Swing的主要特性
-  开发Java applets
-  读写文件和其它数据源
-  在不使用GUI的情况下,对所有数据源执行输入输出
-  理解多线程基础
-  开发多线程Java应用程序和applets
-  使用TCP/IP和用户数据报协议(UDP)开发客户和服务器程序
五、从各模块中所获得的技能
下表的左侧显示有关的Java应用程序编程技能,右侧的黑格表示出讲解其左侧相应技能的有关模块,而灰格则表示简述其左侧相应技能的有关模块。

作者: starlight    时间: 2004-12-1 10:17     标题: SUN JAVA标准教程

六、课时安排
下表给出了大致的课程进度
                 Module               Day    Day    Day    Day    Day
                                        1      2       3      4       5
About This Course                      A.M.
Module 1-Getting Started                 A.M.
Module 2-Identifiers,Keywords,and Types   A.M.
Module 3-Expressions and Flow Control     P.M.
Module 4-Arrays                        P.M.
Module 5-Objects and Classes                    A.M.
Module 6-Advanced Language Features             P.M.
Module 7-Exceptions                                   A.M.
Module 8-Building GUIs                                A.M.
Module 9-The AWT Event Model                          P.M.
Module 10-The AWT Component Library                          A.M.
Module 11-Introduction to JFC                                   A.M.
Module 12-Introduction to Applets                                 P.M.
Module 13-Threads                                            A.M.
Module 14-Stream I/O and Files                                          P.M.
Module 15-Networking                                                 P.M.

七、未包括的论题
未包括的论题
-一般编程概念。本课程不是为从未参与过编程的人员而设置。
-一般面向对象概念。

作者: starlight    时间: 2004-12-1 10:18     标题: SUN JAVA标准教程

本课程未包括的论题见上表,由SUN Educational Services(SES)提供的其它课程包括了上述论题。
-面向对象的概念──见OO-100:面向对象的技术和概念
-面向对象的设计和分析──见OO-120面向对象的设计和分析
-一般编程概念──见SL-110:非程序员Java编程
八、如何做好准备?
如何做好准备?
在学习本课程前,你应该已经完成了下列内容的学习:
-SL-110  非程序员Java编程
-用C或C++创建编译程序
-用文本编辑器创建并编辑文本文件
-使用World Wide Web(WWW)浏览器,如Netscape NavigatorTM
    在学习本课程前,你应该已经完成了下列内容的学习:
-SL-110  非程序员Java编程
或能够:
-用C或C++创建编译程序
-用文本编辑器创建并编辑文本文件
-使用World Wide Web(WWW)浏览器,如Netscape NavigatorTM
九、自我介绍:
自我介绍
-姓名
-公司
-职务、职责
-编程经历
-参与本课程学习的原因
-对本课程的预期
现在你已经进入本课程的学习,请互相介绍并填写上面的表格。
十、如何使用本教材
如何使用本教材
-课程图
-相关问题
-页头图
-教程
-练习
-检查你的进度
-思考题
    为使你学好本课程,本教材采用了包括下列主要项目的授课模式:
课程图──每一模块都从内容概述开始,这样你就可以了解该模块在实现整个课程目标中所起的作用。
相关问题──每一模块的相关问题部分提供给你一些有关该模块的问题供学习者之间进行讨论,并鼓励你思考在Java应用程序编程过程中你的兴趣与该模块内容的关系
页头图──页头图可帮助你及时而轻松的跟上教师的进度。它并不是在每一页都出现

作者: starlight    时间: 2004-12-1 10:19     标题: SUN JAVA标准教程

教程──教师将为你提供有关模块的特有信息,这些信息将有助于你掌握做练习所需要的知识和技能
练习──练习将为你提供测试你的技能和应用所学概念的机会。本教程中所提供的例题代码亦有助于你完成练习。
检查你的进度──在这一部分,模块的目标被重新提及,有时是以问题形式出现。这样,在你进入下一模块之前,就可以检查你是否已完成了目前这一模块所要求达到的目标。
思考题──具有挑战性的问题有助于你应用所学模块内容或预测待学模块的内容。
十一、图表和印刷体例说明
下列图表及印刷体例代表着不同的含义:
辅助资源──表示可获取辅助参考资料。
讨论──表示此时建议以小组或班级形式进行讨论。
练习目标──表示练习的目标,这个练习适合于正在讨论的内容。

注意──附加重要信息、强调信息、有趣或特殊信息

警告──对数据或机器的潜在损坏
印刷体例
字体Courier系用来表示命令名称、文件名及目录名,同时也表示计算机屏幕输出。例如:
Use ls –al to all files.
System% You have mail
黑体courier bold系用来表示你打印的字符和数字。
例如:
system% su
Password:
   
斜体courier italic系用来表示变量和命令行,它可以被实际名称或值所代替。
例如:
To delete a file, type rm filename.
斜体Palatino系用来表示书名、新词或术语或需强调的词。
例如:
Read Chapter 6 in User’s Guide.
These are called class options
You must be root to do this.

作者: starlight    时间: 2004-12-1 10:21     标题: SUN JAVA标准教程

. Available:
http://www.javasoft.com/sfaq/verifier.html.

第三节什么是Java编程语言 ?
什么是Java编程语言
Java是:
-一种编程语言
-一种开发环境
-一种应用环境
-一种部署环境
-句法与C++相似,语义与Small Talk相似
-用来开发applets,又用来开发applications

作者: starlight    时间: 2004-12-1 10:22     标题: SUN JAVA标准教程

Java是:
-一种编程语言
-一种开发环境
-一种应用环境
-一种部署环境
     Java编程语言的句法与C++的句法相似,语义则与Small Talk TM的语义相似。Java编程语言可被用来创建任何常规编程语言所能创建的应用程序。
在World  Wide  Web(WWW)和能够运行称为applets程序的浏览器的有关介绍中,人们经常提及Java编程语言。Applets是一种贮存于WWW服务器的用Java编程语言编写的程序,它通常由浏览器下载到客户系统中,并通过浏览器运行。Applets通常较小,以减少下载时间,它由超文本标识语言(HTML)的Web页来调用。
Java applications是一种独立的程序,它不需要任何Web浏览器来执行。它们是一种典型的通用程序;可运行于任何具备Java运行环境的设备中。
1.3.1  Java编程语言的主要目标
Java编程语言的主要目标
提供一种解释环境为
-提高开发速度
-代码可移植性
-使用户能运行不止一个活动线程
-当程序运行时,能动态支持程序改变
提供更好的安全性
  设计Java编程语言的主要目标是
提供一种易于编程的语言,从而
消除其它语言在诸如指针运算和存储器管理方面影响健壮性的缺陷。
利用面向对象的概念使程序真正地成为可视化程序
为使代码尽可能清晰合理、简明流畅提供了一种方法
Java编程语言的主要目标
设计Java编程语言的主要目标是
提供一种易于编程的语言
-消除其它语言在诸如指针运算和存储器管理方面影响健壮性的缺陷。
-利用面向对象的概念使程序真正地成为可视化程序
-为使代码尽可能清晰合理、简明流畅提供了一种方法
Java编程语言的主要目标(续)
- 为获得如下两点益处提供一种解释环境
提高开发速度──消除编译─链接—装载—测试周期。
代码可移植性──使操作系统能为运行环境做系统级调用
- 为运行不止一个活动线程的程序提供了一种方式
- 通过允许下载代码模块,从而当程序运行时也能动态支持程序改变。
- 为那些保证安全性而装载的代码模块提供了一种检查方法。

作者: starlight    时间: 2004-12-1 10:23     标题: SUN JAVA标准教程

Java编程语言的主要目标
下列特性使这些目标付诸实现:
-Java虚拟机(JVM)
-垃圾收集
-代码安全性
Java编程语言的主要目标(续)
    精心开发的Java技术体系结构为上述目标的实现提供了保证。Java的如下特性使这些目标得以实现
- Java虚拟机
- 垃圾收集
- 代码安全性
1.3.2  Java虚拟机
Java虚拟机
-提供硬件平台规范
-解读独立于平台的已编译的字节码
-可当作软件或硬件来实现
-可在Java技术开发工具或Web浏览器上实现
Java虚拟机规范为Java虚拟机(JVM)作了如下定义:
在真实机器中用软件模拟实现的一种想象机器。Java虚拟机代码被存储在 .class文件中;每个文件都包含最多一个public类。
Java虚拟机规范为不同的硬件平台提供了一种编译Java技术代码的规范,该规范使Java软件独立于平台,因为编译是针对作为虚拟机的“一般机器”而做,这个“一般机器”可用软件模拟并运行于各种现存的计算机系统,也可用硬件来实现。
Java虚拟机
JVM为下列各项做出了定义
-指令集(中央处理器[CPU] )
-注册集
-类文件格式
-栈
-垃圾收集堆
-存储区
Java虚拟机(续)
编译器在获取Java 应用程序的源代码后,将其生成字节码,它是为JVM生成的一种机器码指令。每个Java解释器,不管它是Java技术开发工具,还是可运行applets的Web浏览器,都可执行JVM。
JVM为下列各项做出了定义
-指令集(相当于中央处理器[CPU] )
-注册集
-类文件格式
-栈
-垃圾收集堆
-存储区
Java虚拟机
-由保持适当类型约束的字节码形成代码
-大部分类型检查在编译代码时完成
-每个由SUN TM批准的JVM必须能够运行任何从属类文件

作者: starlight    时间: 2004-12-1 10:24     标题: SUN JAVA标准教程

Java虚拟机(续)
JVM的代码格式由紧缩有效的字节码构成。由JVM字节码编写的程序必须保持适当的类型约束。大部分类型检查是在编译时完成。
任何从属的Java技术解释器必须能够运行任何含有类文件的程序,这些类文件应符合Java虚拟机规范中所指定的类文件格式。
1.3.3  垃圾收集




    许多编程语言都允许在程序运行时动态分配存储器,分配存储器的过程由于语言句法不同而有所变化,但总是要将指针返回到存储区的起始位置
    当分配存储器不再需要时(存储器指针已溢出范围),程序或运行环境应取消分配存储器。
在C,C++ 或其它语言中,程序员负责取消分配存储器。有时,这是一件很困难的事情。因为你并不总是事先知道存储器应在何时被释放。当在系统中没有能够被分配的存储器时,可导致程序瘫痪,这种程序被称作具有存储器漏洞。
Java编程语言解除了程序员取消分配存储器的责任,它可提供一种系统级线程以跟踪每一存储器的分配情况。在Java虚拟机的空闲周期,垃圾收集线程检查并释放那些可被释放的存储器。
    垃圾收集在Java技术程序的生命周期中自动进行,它解除了取消分配存储器的要求,并避免了存储器漏洞。然而,垃圾收集可在JVM实现的周期中,产生意想不到的变化。
1.3.4  代码的安全性
概述
下图显示了Java技术的运行环境及其加强代码安全性的方法。

作者: starlight    时间: 2004-12-1 10:27     标题: SUN JAVA标准教程

Java源程序文件通过“编译”,在你的感觉中,就好象是将它们从程序员编写的文本文件格式转换成了一组字节码。字节码被存储在 .class文件中。
构成Java软件程序的字节码在运行时被加载、校验并在解释器中运行。当运行applets时,字节码可被下载,然后由建于浏览器中的JVM进行解释。解释器具备两种功能,一是执行字节码,二是对底层硬件做适当调用。
在一些使用Java技术的运行环境中,部分校验过的字节码被编译成原始机器码并直接运行于硬件平台。这就使Java软件代码能够以C或C++接近的速度运行,只是在加载时, 因为要编译成原始机器码而略有延迟。
   
注意--SUN MicrosystemsTM通过采用新的技术,使Java虚拟机的性能已经有了进一步的提高。这种新型虚拟机被称为HotSpotTM虚拟机,它具备了使Java编程语言能象编译C++一样快速运行的潜力。HotSpot虚拟机对操作系统具有本地多线程支持能力,而不是虚拟多线程。因而,HotSpot虚拟机可保证对一个应用程序来说,并不一定有代码才能使用这一能力。HotSpot技术解决了性能与移植性之间的难题。

作者: starlight    时间: 2004-12-1 10:29     标题: SUN JAVA标准教程

代码安全性(续)
  Java运行环境
一个Java技术的运行环境可运行为JVM编译的代码并执行如下三大任务:
-加载代码-由类加载器执行
-校验代码-由字节码校验器执行
-执行代码-由运行时的解释器执行
    类加载器
    类加载器为程序的执行加载所需要的全部类。类加载器将局部文件系统的类名空间与来自网络源的类名空间相分离,以增加安全性。由于局部类总是首先加载,因而可限制任何“特洛依木马”的应用。
当全部类被加载后,可执行文件的存储器格式被确定。这时,特定的存储器地址被分配给符号引用并创建检索表格。由于存储器格式在运行时出现,因而Java技术解释器增加了保护以防止对限制代码区的非法进入。

作者: starlight    时间: 2004-12-1 10:32     标题: SUN JAVA标准教程

代码安全性(续)
字节码校验器
Java软件代码在实际运行之前要经过几次测试。JVM将代码输入一个字节码校验器以测试代码段格式并进行规则检查--检查伪造指针、违反对象访问权限或试图改变对象类型的非法代码。
注意----所有源于网络的类文件都要经过字节码校验器

    代码安全性(续)
校验过程
字节码校验器对程序代码进行四遍校验,这可以保证代码符合JVM规范并且不破坏系统的完整性。如果校验器在完成四遍校验后未返回出错信息,则下列各点可被保证:
-  类符合JVM规范的类文件格式
-  无访问限制违例
-  代码未引起操作数栈上溢或下溢
-  所有操作代码的参数类型将总是正确的
-  无非法数据转换发生,如将整数转换为对象引用
-  对象域访问是合法的

作者: starlight    时间: 2004-12-1 10:33     标题: SUN JAVA标准教程

第四节一个基本的Java应用程序
象其它编程语言一样,Java编程语言也被用来创建应用程序。一个共同的小应用程序范例是在屏幕上显示字串“Hello World!”。下列代码给出了这个Java应用程序。
1.4.1  HelloWorldApp
   1.//
   2.// Sample HelloWorld application
   3.//
   4.public class HelloWorldApp{
   5.public static void main (String args[]) {
   6.System.out.println ("Hello World!");
   7.}
   8.}
以上程序行是在你的屏幕上打印“Hello World!”所需的最少组件。
1.4.2  描述HelloWorldApp
第1-3行
程序中的1-3行是注释行
1 //
2 // Sample HelloWorld application
3 //
    第4行
第4行声明类名为HelloWorldApp。类名(Classname)是在源文件中指明的,它可在与源代码相同的目录上创建一个classname•class文件。在本例题中,编译器创建了一个称为HelloWorldApp.class的文件, 它包含了公共类HelloWorldApp的编译代码。
4 public class HelloWorldApp{
第5行
第5行是程序执行的起始点。Java技术解释器必须发现这一严格定义的点,否则将拒绝运行程序。
其它程序语言(特别是C和C++)也采用main ()声明作为程序执行的起始点。此声明的不同部分将在本课程的后几部分介绍。
如果在程序的命令行中给出了任何自变量,它们将被传递给main()方法中被称作args的String数组。在本例题中,未使用自变量。
5 public static void main (String args[]) {
-public-方法main()可被任何程序访问,包括Java技术解释器。
-static- 是一个告知编译器main()是用于类HelloWorldApp中的函数的关键字。为使main()在程序做其它事之前就开始运行,这一关键字是必要的。
-void- 表明main()不返回任何信息。这一点是重要的,因为Java编程语言要进行谨慎的类型检查,包括检查调用的方法确实返回了这些方法所声明的类型。
-String args  - 是一个String数组的声明,它将包含位于类名之后的命令行中的自变量。
    java HelloWorldApp args[0]args[1]••••
第6行
第6行声明如何使用类名、对象名和方法调用。它使用由System类的out成员引用的PrintStreamout对象的println()方法,将字串“Hello World!”打印到标准输出上。
6    System.out.println (“Hello World!”);
在这个例子中,println()方法被输入了一个字串自变量并将其写在了标准输出流上。
第7-8行
本程序的7-8行分别是方法main()和类HelloWorldApp的下括号。
7          }
8       }

作者: starlight    时间: 2004-12-1 10:33     标题: SUN JAVA标准教程

1.4.3  编译并运行HelloWorldApp
      编译并运行HelloWorldApp
-编译HelloWorldApp.java
        javac HelloworldApp.java
-运行应用程序
        java HelloWorldApp
-判定编译和运行的共同错误
编译
当你创建了HelloWorldApp.java源文件后,用下列程序行进行编译:
    c:\student\javac HelloWorldApp.java
如果编译器未返回任何提示信息,新文件HelloWorldApp.class则被存储在与源文件相同的目录中,除非另有指定。
如果在编译中遇到问题,请参阅本模块的查错提示信息部分。
运行
为运行你的HelloWorldApp应用程序,需使用Java解释器和位于bin目录下的java:
           c:\student\ java HelloWorldApp
           Hello World!
注意-必须设置PATH环境变量以发现java和javac,确认它包括c:\jdk1.2\bin
1.4.4  编译查错
    编译时的错误   
    以下是编译时的常见错误
-javac:Command not found
    PATH变量未正确设置以包括javac编译器。javac编译器位于JDK目录下的bin目录。
-HelloWorldApp.java:6: Method printl(java.lang.String)
not found in class java.io.PrintStream.System.
out.printl ("Hello World!");  
    方法名println 出现打印错误。
-In class HelloWorldApp:main must be public or static
该错误的出现是因为词static 或public被放在了包含main方法的行之外。
    运行时的错误
-can’t find class HelloWorldApp       (这个错误是在打印java HelloWorldApp时产生的)
    通常, 它表示在命令行中所指定的类名的拼写与filename.class文件的拼写不同。Java编程语言是一种大小写区别对待的语言。
    例如:     public class HelloWorldapp 
    创建了一个HellloWorldapp.class,它不是编译器所预期的类名(HelloWorldApp.class)。
-命名
    如果•java文件包括一个公共类,那么它必须使用与那个公共类相同的文件名。例如在前例中的类的定义是
    public class HelloWorldapp
    源文件名则必须是HelloWorldapp.java
-类计数
在源文件中每次只能定义一个公共类。

作者: starlight    时间: 2004-12-1 10:34     标题: SUN JAVA标准教程

源文件布局
源文件布局
包含三个“顶级”要素
-一个可选择的包声明
-任意数量的输入语句
-类和界面声明
一个Java源文件可包含三个“顶级”要素:
-   一个包声明(可选)
-   任意数量的输入语句
-   类和界面声明
该三要素必须以上述顺序出现。即,任何输入语句出现在所有类定义之前;如果使用包声明,则包声明必须出现在类和输入语句之前。
第五节类和包介绍
类和包介绍
1.什么是类和包?
2.Java类库中的几个重要包
       java.lang
       java.awt
       java.applet
       java.net
       java.io
       java.util
类是描述提供某种功能的模块的一般术语。Java开发集(JDK)给出了一套标准的类(称作类库),这些类可执行大部分所需的基本行为     不仅为编程任务(例如,类可提供基本的数学函数、数组和字符串),而且为图形和网络。
类库被组织成许多包,每个包都包含几个类。如下所列为一些重要的包:
java.lang包含一些形成语言核心的类,如String、Math、Integer和Thread。
java.awt包含了构成抽象窗口工具包(AWT)的类,这个包被用来构建和管理应用程序的图形用户界面。
java.applet包含了可执行applet特殊行为的类。
    java.net包含执行与网络相关的操作的类和处理接口及统一资源定位器(URLs)的类。
    java.io包含处理I/O文件的类。
java.util包含为任务设置的实用程序类,如随机数发生、定义系统特性和使用与日期日历相关的函数。
第六节使用Java API文档
使用Java API文档
1.一组超文本标识语言(HTML)文件提供了有关API的信息
2.一个包包含了对所有类信息的超链接
3.一个类文档包括类层次、一个类描述、一组成员变量和构造函数等
一组HTML文件以文档的形式提供了有关API的信息,这个文档的布局是等级制的,因而主页列出所有的包为超链接。如果选中了一个特殊包的热链接,作为那个包成员的类将被列出。从一个包页选中一个类的热链接将提交一页有关那个类的信息。

作者: starlight    时间: 2004-12-1 10:35     标题: SUN JAVA标准教程

图1-1显示了这样一个类文档


图1-1
一个类文档的主要部分包括:
-类层次
-类和类的一般目的描述
-成员变量列表
-构造函数列表
-方法列表
-变量详细列表及目的和用途的描述
-构造函数详细列表及描述
-方法详细列表及描述
练习:基本任务
练习目标--在本练习里,你将利用Java API文档练习如何识别包、类和方法并练习标准输入输出方法。你还将编写、编译和运行两个简单的使用这些方法的应用程序。
一、准备
理解本模块中提出的概念和术语对理解文件和运用文件信息编写程序至关重要。
二、任务
1级:阅读文件
1.你的老师将指导你如何启动API浏览器并打开Java API在线文档的索引页。
2.找到java.lang包
3.在此包中定义了那些类?在System类中有那些方法?System.out.println方法是在什么包中定义的?什么是标准输入方法调用?
2级:创建一个Java应用程序
1.使用任意文本编辑器,创建一个可打印你选定的字串的与HelloWorldApp类似的应用程序。
2.编译程序并纠正错误。
3.用解释器运行程序。
3级:使用标准输入和标准输出
编写一个称为MyCat的应用程序,它将从stdin中读出一行并将这一行写回到stdout. 无论stdin还是stdout都在java.lang.System类中。
三、检查你的进度
在进入下一模块之前,请确认你已经能够:
-描述Java编程语言的主要特性
-描述JVM
-描述垃圾收集是如何进行的
-列出由处理代码安全性的Java平台所执行的三个任务
-定义术语类、包、applets和application
-编写、编译并运行一个简单的Java应用程序
-使用Java技术应用程序编程界面(API)的在线文档识别java.lang包中的方法。
四、思考题
使用Java编程语言将为你的工作带来什么益处?

作者: starlight    时间: 2004-12-1 11:09     标题: SUN JAVA标准教程

第二章  标识符、关键字和类型
本模块阐述了在Java技术程序中使用的基本元素,包括变量、关键字、原始类型和类类型。

第一节  相关问题
讨论──下列问题与本模块阐述的论题相关。
- 你是如何理解类的?
- 你是如何理解一个对象的?
第二节  目标
完成本模块的学习后,你应该能够:
- 在一个源程序中使用声明
- 区分有效和无效标识符
- 确认Java技术关键字
- 列出八个原始类型
- 为数字类型和文本类型定义文字值
- 定义术语class、object、member variable和reference variable
- 为一个简单的包含原始成员变量的类创建一个类定义
- 声明类类型变量
- 使用new构造一个对象
- 描述缺省初始化
- 使用点符号访问一个对象的成员变量
- 描述一个参考变量的意义
- 规定分配类类型变量的结果
第三节注 释
注释
三种允许的Java技术程序注释风格
          //comment on one line
          /* comment on one
          or more line */
          /** documenting comment */
2.3.1  概述
有三种插入注释的允许风格:
          //comment on one line
          /* comment on one or more line */
          /** documenting comment */
紧放在声明(变量、方法或类的声明)之前的文档注释表明, 注释应该被放在自动生成的文档中(由javadoc命令生成的HTML文件)以当作对声明项的描述。

注意------有关这些注释的格式和 javadoc工具的使用,请见JDK1.2 API文件的  docs/tooldocs/win32目录

2.3.2分号、块和空白
分号、块和空白
-一个语句是一行用分号(;) 终止的代码   
     totals=a+b+c+d+e+f;
-一个块是以上括号和下括号为边界的语句集合
      
          x=y+1
          y=x+1
      
    在Java编程语言中,语句是一行由分号(;)终止的代码。
    例如
               totals=a+b+c+d+e+f;
       与下式相同
           total=a+b+c+
            d+e+f;
一个块(block)或一个复合语句是以上括号和下括号()为边界的语句集合;块语句也被用来组合属于某个类的语句。

作者: starlight    时间: 2004-12-1 11:09     标题: SUN JAVA标准教程

分号、块和空白(续)
分号、块和空白
-一个块可被用在一个类的定义中
      public class Date 
         int day;
         int month;
         int year;
      
-块语句可被嵌套
-Java程序中允许任意多的空白
语句块可被嵌套。HelloWorldApp类由main方法构成,这个方法就是一个语句块,它是一个独立单元,单元本身可作为在类HelloWorldApp块中的一组事务之一。
    其它一些块语句或组的例子如下:
   
   // a block statement
{
x = y + 1;
y = x + 1;
}
Semicolons, Blocks, and Whitespace
// a block used in a class definition
public class MyDate {
int day;
int month;
int year;
}
// an example of a block statement nested within
// another block statement
while ( i < large ) {
a = a + i;
if ( a == max ) {
b = b + a; // nested block is here
a = 0;
}
}
在源代码元素之间允许空白,空白的数量不限。空白(包括空格、tabs和新行)可以改善你的对源代码的视觉感受。
{
int x;
x = 23 * 54;
}
   
   
    int  x
    x  =  23  +  54;
}

作者: starlight    时间: 2004-12-1 11:11     标题: SUN JAVA标准教程

第四节  标识符
                    标识符
-是赋予变量、类和方法的名称
-可从一个字母、下划线(_)或美元符号($)开始
-是大小写区别对待的, 且无最大长度
    在Java编程语言中,标识符是赋予变量、类或方法的名称。标识符可从一个字母、下划线(_)或美元符号($)开始,随后也可跟数字。标识符是大小写区别对待的并且未规定最大长度。
    有效标识符如下:
-identifier
-userName
-User_name
-_sys_varl
-$change
Java技术源程序采用有效的16-bit 双字节字符编码标准(Unicode) ,而不是8-bit ASCII文本。因而,一个字母有着更广泛的定义,而不仅仅是a到z和A到Z。
谨慎对待非ASCII字符,因为Unicode可支持看似相同而实际不同 的字符。
标识符不能是关键字,但是它可包含一个关键字作为它的名字的一部分。例如,thisone是一个有效标识符,但this却不是,因为this是一个Java关键字。Java关键字将在后面讨论。
注意──包含美元符号($)的关键字通常用的较少, 尽管它在BASIC和VAX/VMS系统语言中有着广泛的应用。由于它们不被熟知, 因而最好避免在标识符中使用它们, 除非有本地使用上的习惯或其他不得已的原因。

第五节  Java关键字
表2-1列出了使用在Java编程语言中的关键字。
abstract    do     implements  private    throw
boolean    double  import      protected  throws
break      else    instanceof   public    transient
byte       extends int         return     true
case       false   interface    short      try
catch      final   long        static      void
char       finally  native      super      volatile
class      float    new       switch     while
continue   for     null        synchronized
default     if      package    this
关键字对Java技术编译器有特殊的含义,它们可标识数据类型名或程序构造(construct)名。
以下是有关关键字的重要注意事项:
- true、false和null为小写,而不是象在C++语言中那样为大写。严格地讲,它们不是关键字,而是文字。然而,这种区别是理论上的。
- 无sizeof运算符;所有类型的长度和表示是固定的,不依赖执行。
- goto和const不是Java编程语言中使用的关键字。

作者: starlight    时间: 2004-12-1 11:14     标题: SUN JAVA标准教程

第六节  基本Java类型
Java编程语言定义了八个原始类型
-逻辑类   boolean
-文本类   char
-整数类   byte, short, int, long
-浮点类   double, float
2.6.1  原始类型
Java编程语言为八个原始数据类型和一个特殊类型定义了文字值。原始类型可分为四种:
-逻辑类   boolean
-文本类   char
-整数类   byte, short, int, long
-浮点类   double, float
2.6.2  基本Java类型
1.逻辑类──boolean
逻辑类──boolean
boolean  数据类型有两种文字值:true和false。
例如:boolean  truth  =  true;
上述语句声明变量truth为boolean 类型,它被赋予的值为true。
逻辑值有两种状态,即人们经常使用的“on”和“off” 或“true”和“false”或“yes”和“no”,这样的值是用boolean类型来表示的。boolean有两个文字值,即true和false。以下是一个有关boolean类型变量的声明和初始化:
boolean truth = true; //declares the variable truth
                 //as boolean type and assigns it
                 //the value true
注意──在整数类型和boolean类型之间无转换计算。有些语言(特别值得强调的是C和C++)允许将数字值转换成逻辑值, 这在Java编程语言中是不允许的;boolean类型只允许使用boolean值。

2.文本类──char和String
文本类──char和String
char
-代表一个16-bit Unicode字符
-必须包含用单引号(’’)引用的文字
-使用下列符号:
    ‘a’
    ‘\t’        一个制表符
   ‘\u????’    一个特殊的Unicode字符,????应严格使用四个16进制数进行替换
使用char类型可表示单个字符。一个char代表一个16-bit无符号的(不分正负的)Unicode字符。一个char文字必须包含在单引号内(‘’)。
‘a’
‘\t’       一个制表符
‘\u????’   一个特殊的Unicode字符。????应严格按照四个16进制数字进行替换
String不是原始类型,而是一个类(class),它被用来表示字符序列。字符本身符合Unicode标准,且上述char类型的反斜线符号适用于String。与C和C++不同,String不能用 \0作为结束。
文本类──char和String
String
-不是一个原始数据类型,它是一个类
-具有用双引号引用的文字
“The  quick brown fox jumped over the lazy dog.”
-   可按如下情形使用:
String greeting =  “Good Morning!! \n”;
String err_meg = “ record not found !”;

作者: starlight    时间: 2004-12-1 11:16     标题: SUN JAVA标准教程

文本类──char和String (续)
String的文字应用双引号封闭,如下所示:
“The  quick brown fox jumped over the lazy dog.”
Char和String类型变量的声明和初始化如下所示:
   char ch = `A'; // declares and initializes a char variable
   char ch1,ch2 ; // declares two char variables
  // declare two String variables and initialize them
  String greeting = "Good Morning !! \n" ;
  String err_msg = "Record Not Found !" ;
  String str1,str2 ; // declare two String variables
2.6.3  整数类──byte, short, int, long
整数类──byte, short, int, long
   
采用三种进制──十进制、八进制和16进制
2        十进制值是2
077      首位的0表示这是一个八进制的数值
0xBAAC  首位的0x表示这是一个16进制的数值
具有缺省int
用字母“L”和“l”定义long
在Java编程语言中有四种整数类型,每种类型可使用关键字byte, short, int和long中的任意一个进行声明。整数类型的文字可使用十进制、八进制和16进制表示,如下所示:
2        十进制值是2
077      首位的0表示这是一个八进制的数值
    0xBAAC  首位的0x表示这是一个16进制的数值

注意──所有Java编程语言中的整数类型都是带符号的数字。

整数类──byte, short, int, long(续)
整数类文字属int类型,除非在其后直接跟着一个字母“L”。L表示一个long值。请注意,在Java编程语言中使用大写或小写L同样都是有效的,但由于小写l与数字1容易混淆,因而,使用小写不是一个明智的选择。上述文字的long的形式如下:
2L        十进制值是2,是一个long
077L      首位的0表示这是一个八进制的数值
0xBAACL  前缀0x表示这是一个16进制的数值
整数类──byte, short, int, long
每个整数数据类型具有下列范围:
Integer Length  Name or Type  Range
8 bits         byte         -2 7 ... 2 7 -1
16 bits        short        -2 15 ... 2 15 -1
32 bit         int          -2 31 ... 2 31 -1
64 bits        long         -2 63 ... 2 63 -1
整数类──byte, short, int, long(续)
四个整数类型的长度和范围如表2-2所示。范围的表示是按Java编程语言规范定义的且不依赖于平台。
表2-2  整数数据类型—范围
Integer Length  Name or Type  Range
8 bits         byte         -2 7 ... 2 7 -1
16 bits        short        -2 15 ... 2 15 -1
32 bit         int          -2 31 ... 2 31 -1
64 bits        long         -2 63 ... 2 63 -1
2.6.4 浮点──float和double
浮点──float和double
-缺省为double
-浮点文字包括小数点或下列各项之一
-E或e  (增加指数值)
-F或f  (float)
-D或d  (double)
3.14            一个简单的浮点值(a double)
4.02E23         一个大浮点值
            2.718F        一个简单的float长度值
            123.4E+306D  一个大的带冗余D的double值
    浮点变量可用关键字float或double来声明,下面是浮点数的示例。如果一个数字文字包括小数点或指数部分,或者在数字后带有字母F或f(float)、D或d(double),则该数字文字为浮点。
3.14            一个简单的浮点值(a double)
4.02E23         一个大浮点值
            2.718F        一个简单的float长度值
            123.4E+306D  一个大的带冗余D的double值
浮点──float和 double
浮点数据类型具有下列范围:
     浮点长度               名称或类型
      32 bits                   float
      64 bits                   double

作者: starlight    时间: 2004-12-1 11:16     标题: SUN JAVA标准教程

2.6.4 浮点──float和double
浮点──float和double
-缺省为double
-浮点文字包括小数点或下列各项之一
-E或e  (增加指数值)
-F或f  (float)
-D或d  (double)
3.14            一个简单的浮点值(a double)
4.02E23         一个大浮点值
            2.718F        一个简单的float长度值
            123.4E+306D  一个大的带冗余D的double值
    浮点变量可用关键字float或double来声明,下面是浮点数的示例。如果一个数字文字包括小数点或指数部分,或者在数字后带有字母F或f(float)、D或d(double),则该数字文字为浮点。
3.14            一个简单的浮点值(a double)
4.02E23         一个大浮点值
            2.718F        一个简单的float长度值
            123.4E+306D  一个大的带冗余D的double值
浮点──float和 double
浮点数据类型具有下列范围:
     浮点长度               名称或类型
      32 bits                   float
      64 bits                   double
浮点──float和 double(续)
   
       表2—3  浮点数据类型──范围
     
     浮点长度               名称或类型
      32 bits                   float
      64 bits                   double

注意──浮点文字除非明确声明为float,否则为double

第七节  变量、声明和赋值
Java技术规范的浮点数的格式是由电力电子工程师学会(IEEE)754定义的,它使用表2—3的长度,并且是独立于平台的。
下列程序显示了如何为整数、浮点、boolean、字符和string类型变量声明和赋值。
   1. public class Assign {
   2. public static void main(String args []) {
   3. int x, y; // declare int
     // variables
   4.float z = 3.414f; // declare and assign
     // float
   5.double w = 3.1415; // declare and assign
     // double
   6.boolean truth = true; // declare and assign
     // boolean
   7.char c; // declare character
     // variable
   8.String str; // declare String
   9.String str1 = "bye"; // declare and assign
     // String variable
  10.c = 'A'; // assign value to char
     // variable
  11.str = "Hi out there!"; // assign value to
     // String variable
  12.x = 6;
  13.y = 1000; // assign values to int variables
  14....
  15.}
  16.}
非法赋值举例
y = 3.1415926; // 3.1415926 is not an int.
             // Requires casting and decimal will
             // be truncated.
w = 175,000; // the comma symbol ( , ) cannot appear
truth = 1; // a common mistake made by ex- C / C++
            // programmers.
z = 3.14156 ; //can't fit double into a
           //Float. Requires casting.

作者: starlight    时间: 2004-12-1 11:18     标题: SUN JAVA标准教程


第八节  Java编码约定
                java编码约定
 类:
                class  AccouJntBook
                class  ComplexVariable
 界面:
                interface  Account
 方法:
                balanceAccount()
                addComplex ()
    Java编程语言的一些编码约定是:
    classes──类名应该是名词,大小写可混用,但首字母应大写。例如:
                class  AccountBook
                class  ComplexVariable
    interface──界面名大小写规则与类名相同。
                interface  Account
    method──方法名应该是动词,大小写可混用,但首字母应小写。在每个方法名内,大写字母将词分隔并限制使用下划线。例如:
                balanceAccount()
                addComplex ()
                 Java编码约定
变量
currentCustomer
常量
HEAD-COUNT
MAXIMUM-SIZE
Java编码约定
Variables──所有变量都可大小写混用,但首字符应小写。词由大写字母分隔,限制用下划线,限制使用美元符号($),因为这个字符对内部类有特殊的含义。
         currentCustomer
变量应该代表一定的含义,通过它可传达给读者使用它的意图。尽量避免使用单个字符, 除非是临时“即用即扔”的变量(例如,用i, j, k作为循环控制变量)
constant──原始常量应该全部大写并用下划线将词分隔;对象常量可大小写混用。
         HEAD-COUNT
         MAXIMUM-SIZE
   control structures──当语句是控制结构的一部分时,即使是单个语句也应使用括号({})将语句封闭。例如:
if  (condition) {
   do something
}else  {
   do something else

spacing── 每行只写一个语句并使用四个缩进的空格使你的代码更易读。
comments──用注释来说明那些不明显的代码段落;对一般注释使用 //  分隔符, 而大段的代码可使用 /*•••*/分隔符。使用 /**•••*/将注释形成文档,并输入给javadoc以生成HTML代码文档。
// A comment that takes up only one line.
/* Comments that continue past one line and take up space on multiple lines...*/
/** A comment for documentation purposes.
@see Another class for more information
*/
注意──@see是一个有关类或方法的特殊的javadoc标记符(”see also”)。有关javadoc的详细资料, 请参见“The Design of Distributed Hyperlinked Programming Documentation”(Lisa著)的有关文档系统的完整定义。该资料可从下列地址获得:http://www.javasoft.com/doc/api_documentation.html.


作者: starlight    时间: 2004-12-1 14:13     标题: SUN JAVA标准教程

第九节  理解对象

理解对象
回顾对象的历史
创建一个新的类型,如date
     public class date{
        int day;
        int month;
        int year;
     }
声明一个变量
        Date myBirth, yourBirth
访问成员
           myBirth.day  = 26;
           myBirth.month = 11;
           yourBirth.year = 1960;

2.9.1  回顾对象的历史
早些时候的编程语言和初级程序员将每个变量看作相互无关的实体。例如,如果一个程序需处理某个日期,则要声明三个单独的整数:
int day, month, year;
上述语句作了两件事,一是当程序需要日、月或年的有关信息时,它将操作一个整数; 二是为那些整数分配存储器。
尽管这种作法很容易理解,但它存在两个重大缺陷。首先,如果程序需同时记录几个日期,则需要三个不同的声明。例如,要记录两个生日,你可能使用:
int  myBirthDay, myBirthMonth, myBirthYear;
int  yourBirthDay, yourBirthMonth, yourBirthYear;
    这种方法很快就会引起混乱,因为需要的名称很多。
    第二个缺陷是这种方法忽视了日、月和年之间的联系并把每个变量都作为一个独立的值,每个变量都是一个独立单元(在本例中为date)的一部分并被相应地处理。
2.9.2  创建一个新类型
    为克服上述两种缺陷,Java编程语言使用类来创建新类型。请看下列原始类型声明:
         int  day;
    Java编程语言被用来分配一定量的存储器并解释该存储器的内容。于是,要定义一个新的类型,你必须指出需要多大存储器和如何解释存储器内容。这不是根据字节数或位的顺序和含义来做,而是根据已经定义的其它类型来做。
    例如,要定义一个表示日期的类型,你需要足够的存储器存储三个整数变量;进而,日、月和年的意义即由这些整数变量给出。如下所示:
       class MyDate  
      int day;
      int month;
      int year;
      
词class是Java编程语言的一个关键字,必须全部小写。名称MyDate按照大小写的有关约定处理,而不是由语意要求来定。
  注意----- class 不仅仅是一个集合数据类型,这个问题以后还将进一步讨论。

    一个变量可被声明为归属于类型MyDate,从而日、月和年部分将被隐含声明。例如:
    MyDate  myBirth, yourBirth;
    使用这个声明,Java编程语言允许变量的部分(day, month和year)通过调用成员和使用点(•)运算符而被访问。例如:
     myBirth.day  =  26;
     myBirth.month = 11;
     yourBirth.year = 1960;

作者: starlight    时间: 2004-12-1 14:14     标题: SUN JAVA标准教程

2.9.3  创建一个对象
创建一个对象
-原始类型的声明可分配存储器空间
-非原始类型的声明不分配存储器空间
-声明的变量不是数据本身, 而是数据的引用(或指针)
   当任何原始类型(如boolean, byte, short,char,int,long,float或double类型) 的变量被声明时,作为上述操作的一部分,存储器空间也同时被分配。使用非原始类型(如String或class)的变量的声明不为对象分配存储器空间。
    事实上,使用class类型声明的变量不是数据本身,而是数据的引用(reference)。
注意----你也可以认为引用是一个指针(pointer), 这可能会有助于你的理解。实际上, 在大多数实现中, 也确实可以这样认为。值得注意的是, Java编程语言实际上不支持指针数据类型。
    在你可以使用变量之前,实际存储器必须被分配。这个工作是通过使用关键字new来实现的。如下所示:
      MyDate myBirth;
      myBirth = new MyDate ();
    第一个语句(声明)仅为引用分配了足够的空间,而第二个语句则通过调用对象为构成MyDate的三个整数分配了空间。对象的赋值使变量myBirth重新正确地引用新的对象。这两个操作被完成后,MyDate对象的内容则可通过myBirth进行访问。
假使定义任意一个class XXXX, 你可以调用new XXXX () 来创建任意多的对象,对象之间是分隔的。一个对象的引用可被存储在一个变量里,因而一个”变量点成员”(如myBirth.day)可用来访问每个对象的单个成员。请注意在没有对象引用的情况下,仍有可能使用对象,这样的对象称作”匿名”对象。
2.9.4  创建一个对象----存储器分配和布局

创建一个对象----存储器分配和布局
一个声明仅为一个引用分配存储器
     MyDate today
     today = new MyDate();
     today
      在一个方法体中,声明
      MyDate today
      today = new MyDate();
      仅为一个引用分配存储器
      today

      关键字new意味着存储器的分配和初始化
MyDate today;
today = new MyDate();
      赋值则建立了引用变量,从而它可适当地引用新的创建对象
     MyDate today;
      today = new MyDate();

作者: starlight    时间: 2004-12-1 14:18     标题: SUN JAVA标准教程

使用一个语句同时为引用today和由引用today所指的对象分配空间也是可能的。
      MyDate today = new MyDate ();
2.9.5  引用类型的赋值

引用变量的赋值
请考虑下列代码片段:
     int x = 7;
     int y = x;
     String s = “Hello”;
     String t = s;

    在Java编程语言中,用类的一个类型声明的变量被指定为引用类型,这是因为它正在引用一个非原始类型,这对赋值具有重要的意义。请看下列代码片段:
     int x = 7;
     int y = x;
     String s = “Hello”;
     String t = s;
    四个变量被创建:两个原始类型 int 和两个引用类型String。x的值是7,而这个值被复制到y;x 和 y是两个独立的变量且其中任何一个的进一步的变化都不对另外一个构成影响。
至于变量 s 和 t,只有一个String 对象存在, 它包含了文本”Hello” ,s 和 t均引用这个单一的对象。


作者: starlight    时间: 2004-12-1 14:21     标题: SUN JAVA标准教程

2.9.6  术语回顾
   术语回顾
-Class
-Object
-Reference type
-member
  
    本模块中介绍了几个术语,简单回顾如下:
-类------在Java编程语言中定义新类型的一种途径。类声明可定义新类型并描述这些类型是如何实现的。有许多关于类的其它特性还未讨论。
-对象------一个类的实例。类可被认为是一个模板------你正在描述一个对象模型。一个对象就是你每次使用new创建一个类的实例的结果。
-引用类型------一个用户定义类型, 它可引用类、界面和数组。
-成员------构成一个对象的元素之一。这个词也被用作定义类的元素(elements)。成员变量(member variabl)、实例变量(instance variable)和域(field)也经常被互换使用。

练习:使用对象
     练习目标──正确使用Java关键字,编写一个创建类的程序并从类创建一个对象。编译并运行程序,然后校验引用是否被赋值并检查引用是不是按照本模块所描述的那样操作的。
一、准备
     为了成功地完成本练习,你必须能够编译并运行Java程序,并且需要熟悉有关类和对象的面向对象的概念和引用的概念。
二、任务
     1级:创建一个类和相应的对象
1.一个点可用x和y坐标描述。定义一个称为MyPoint的类来表达上述想法。你应该称这个文件为什么?
2.在你的类中编写一个类方法,然后为类型MyPoint声明两个变量,将变量称为start和end;用new MyPoint()创建对象并分别将引用值赋予变量start和end;
3.将值10赋予对象start的成员x和y;
4.将值20赋予对象end的x值,将值20赋予对象end的y值。
5.分别打印MyPoint对象(start和end)的成员值(x和y)。

注意----为完成第5步,你需要更多地了解system类。带自变量String的System.out.println()可输出string并开始新的一行,而System.out.print()不开始新的一行。如果你使用System.out.print(),你应该在这个应用程序结束之前,调用System.out.println()或System.out.flush(),否则你会发现,输出的最后一行未被显示出来。
      为显示数字,你可以使用下列形式(稍后将在本课程中讨论)
      System.out.println(“Start MyPoint = x:“+start.x + “ y “ + start.y);
注意--如果一个操作数已经是一个String, 则加号(+)将另一个操作数转换成String。
6.编译并运行程序。
     2级:检验引用赋值
     使用你在前一个练习中MyPoint类,增加代码到main()方法,以完成下列事项:
1.为类型MyPoint声明一个新的变量,称之为stray。将现存变量end的引用值赋予stray;
2.打印end和stray变量的成员x和y的值;
3.赋予变量stray的成员x和y新的值;
4.打印end和stray的成员的值;编译并运行MyPoint类。end的值反映了stray内的变化,表明两个变量都引用了同一个MyPoint对象;
5.将start变量的成员x和y赋予新的值;
6.打印start和end的成员值; 再次编译并运行MyPoint类,start的值仍然独立于stray和end的值,表明start变量仍然在引用一个MyPoint对象,而这个对象与stray和end引用的对象是不同的。
三、练习小结
    讨论──用几分钟的时间讨论一下在以上练习中你所获得的经验、感想和发现。
经验  解释  总结  应用
四、检查你的进度
在进入下一模块之前,请确认你已经能够:
-在源程序中使用注释
-区分有效和无效标识符
-识别Java技术关键字
-列出八个原始类型
-为数字和文本类型定义文字值
-定义术语class, object,member,variable,referrence variable
-为一个简单的包含原始成员变量的类创建一个类定义
-声明类类型的变量
-使用new构造一个对象
-描述缺省初始化
-使用点符号访问一个对象的成员变量
-描述引用变量的意义
-陈述分配类类型变量的结果
五、思考题
    在你现有应用程序中,你可以构思一个使用类和对象的例子吗


作者: starlight    时间: 2004-12-1 14:26     标题: SUN JAVA标准教程

第三章表达式和流程控制
    本模块讨论变量、运算符和算术表达式并列出不同的管理运行程序路径的控制结构。
   
第一节  相关问题
    讨论──下列问题与本模块阐述的论题相关。
-什么类型的变量对程序员有用(例如,其它语言的程序员想了解Java编程语言是如何定义和处理全局变量和局部变量的) ?
-复合类可以有同名的变量吗?如果可以,它们的作用域有多大?
-列出用于其它语言的控制结构;一般语言都采用什么方法进行流程控制和中断流程(如在循环或开关语句中) ?
第二节  目 标
完成本模块的学习后,你应该能够:
-区分实例变量和局部变量;
-描述实例变量是如何被初始化的;
-确认并更正编译器错误;
-辨认、描述并使用Java软件运算符;
-区分合法和非法原始类型赋值;
-确认boolean表达式和它们在控制构造中的要求;
-辨认赋值兼容性和在基本类型中的必要计算;
-使用if, switch,for,while和do句型结构和break和continue的标号形式作为程序中的流程控制结构。
第三节  表达式
3.3.1  变量和作用域

      变量和作用域
-局部(local)变量是在一个方法内定义的变量, 也被称作自动(automatic)、临时(temporary)或栈(stack)变量
-当一个方法被执行时, 局部变量被创建;当一个方法被终止时, 局部变量被清除
-局部变量必须使用之前初始化, 否则编译时将出错
    你已经看到了两种变量的描述方法:原始类型变量和引用类型变量。你也看到了变量被声明的位置:在方法内(方法是面向对象的术语,它可引用函数或子程序,例如:main())或在方法外但在类定义之内。变量也可被定义为方法参数或构造函数参数。
    在方法内定义的参数被称为局部(local)变量,有时也被用为自动(automatic)、临时(temporary)或栈(stack)变量。
    在方法外定义的变量是在使用new Xxxx ()调用构造一个对象时被创建。在构造一个对象时,可创建两种变量。一是类变量,它是用static关键字来声明的;只要需要对象,类变量就将存在。二是实例变量,它不需用static关键字来声明;只要对象被当作引用,实例变量就将存在。实例变量有时也被用作成员变量,因为它们是类的成员。
    方法参数变量定义在一个方法调用中传送的自变量,每次当方法被调用时,一个新的变量就被创建并且一直存在到程序的运行跳离了该方法。
当执行进入一个方法时,局部变量被创建,当执行离开该方法时,局部变量被取消。因而,局部变量有时也被引用为“临时或自动”变量。在成员函数内定义的变量对该成员变量是“局部的”,因而,你可以在几个成员函数中使用相同的变量名而代表不同的变量。 该方法的应用如下所示:

作者: starlight    时间: 2004-12-1 14:27     标题: SUN JAVA标准教程

class OurClass { int i; // instance variable of class OurClass int firstMethod() { int j=0; // local variable // both i and j are accessible from // this point ... return 1; } // end of firstMethod() int secondMethod(float f) { //method parameter int j=0; //local variable. Different from the // j defined in firstMethod(). // Scope is limited to the body of // secondMethod(). // Both i(instance variable of the // class OurClass) and j (local // variable of this method) are // accessible from this point. .... return 2; } // end of secondMethod() } // end of class OurClass 3.3.2 变量初始化 在Java程序中,任何变量都必须经初始化后才能被使用。当一个对象被创建时,实例变量在分配存储器的同时被下列值初始化: byte 0 short 0 int 0 long 0L float 0.0f double 0.0d char '\u0000' (NULL) boolean false All reference types Null 注意── 一个具有空值的引用不引用任何对象。试图使用它引用的对象将会引起一个异常。异常是出现在运行时的错误,这将在模块7“异常”中讨论。 在方法外定义的变量被自动初始化。局部变量必须在使用之前做“手工”初始化。如果编译器能够确认一个变量在初始化之前可被使用的情形,编译器将报错。 public void doComputation() { int x = (int)(Math.random() * 100); int y; int z; if (x > 50) { y = 9; } z = y + x; // Possible use before initialization } 3.3.3 运算符 Java软件运算符在风格和功能上都与C和C++极为相似。表3-1按优先顺序列出了各种运算符(“L to R”表示左到右结合,“R to L”表示右到左结合) Separator [] () ; , R to L ++ -- + - ~ ! (data type) L to R * / % L to R + - L to R << >> >>> L to R < > <= >= instanceof L to R == != L to R & L to R ^ L to R | L to R && L to R || R to L ?: R to L = *= /= %= += -= <<= >>= >>>= &= ^= |= 注意──instanceof是Java编程语言特有的运算符,将在模块5“对象和类”中讨论
作者: starlight    时间: 2004-12-1 14:29     标题: SUN JAVA标准教程

3.3.4  逻辑表达式

逻辑表达式
支持的位运算符如下:
!──NOT          &──AND
|──XOR          ^──OR
布尔运算符如下:
~ ──Complement(取反)      &──AND
^──XOR                | |──OR
多数Java运算符是从其它语言借取得并且和人们一般期待的功能一样。
关系和逻辑运算符返回布尔结果,int到boolean不能自动转换。
     int  i = 1;
     if ( i ) //generates a compile error
     if (i !=0) // Correct
支持的位运算符是!、&、|、^, 支持的布尔逻辑运算符是NOT、AND、XOR和OR。每个运算都返回布尔结果。运算符&&和||是运算符&和|的布尔等价物。布尔逻辑运算符将在下一页中讨论。
3.3.5  位运算
Java编程语言支持整数数据类型的位运算,它们的运算符~、&、^和|分别表示位运算的NOT(为求反)、位AND、位XOR和位OR。移位运算符将稍后在本课程中讨论。
3.3.6  布尔逻辑运算符

布尔逻辑运算符
运算符是&&(AND)和||(OR)
运算符使用举例:
       见3-11页程序
运算符&& (定义为AND)和||(定义为OR)执行布尔逻辑表达式。请看下面的例子:
MyDate d = null;
if ((d! = null) && (d,day() > 31)) {
// do something with d

形成if ()语句自变量的布尔表达式是合法且安全的。这是因为当第一个子表达式是假时,第二个子表达式被跳过,而且当第一个子表达式是假时,整个表达式将总是假,所以不必考虑第二个子表达式的值。类似的,如果使用||运算符,而且第一个表达式返回真, 则第二个表达式不必求值,因为整个表达式已经被认为是真。

3.3.7  用加号(+)进行串链接
用加号(+)进行串链接
运算符 +  能够:
进行String链接
生成一个新的String
例如:
        String salutation = "Dr. ";
        String name = "Jack " + "Arthur";
        String title = salutation + name;
    最后一行的结果是:
        Dr. Jack Arthur
一个自变量必须是String对象
非串被自动转换为String对象
运算符 +  能够进行String对象的链接并生成一个新的String:
        String salutation = "Dr. ";
        String name = "Jack " + "Arthur";
        String title = salutation + name;
      最后一行的结果是:
        Dr. Jack Arthur
如果+运算符中有一个自变量为String对象,则其它自变量将被转换成String。所有对象都可被自动转换成String,尽管这样做的结果可能是意义含糊的。不是串的对象是通过使用toString() 成员函数而转换成串的等价物的。

作者: starlight    时间: 2004-12-1 14:31     标题: SUN JAVA标准教程

3.3.8 右移位运算符>>和>>> 右移位运算符>>和>>> 算术或符号右移位如下所示: 见3-13页 在移位的过程中, 符号位被拷贝 逻辑或非符号右移位运算符(>>>) 作用于位图 在移位的过程中, 符号位不被拷贝 Java编程语言提供了两种右移位运算符 运算符>>进行算术或符号右移位。移位的结果是第一个操作数被2的幂来除,而指数的值是由第二个数给出的。例如: 128 >> 1 gives 128/2 1 = 64 256 >> 4 gives 256/2 4 = 16 -256 >> 4 gives -256/2 4 = -16 逻辑或非符号右移位运算符>>>主要作用于位图,而不是一个值的算术意义;它总是将零置于最重要的位上。例如: 1010 ... >> 2 gives 111010 ... 1010 ... >>> 2 gives 001010 ...在移位的过程中, >>运算符使符号位被拷贝。 注意──移位运算符将它们右侧的操作数模32简化为int类型左侧操作数, 模64简化为long类型右侧操作数。因而, 任何int x, x >>> 32都会导致不变的x值, 而不是你可能预计的零。 注意------值得称赞的重要一点是: >>>运算符仅被允许用在整数类型, 并且仅对int和long值有效。如果用在short或byte值上, 则在应用>>>之前, 该值将通过带符号的向上类型转换被升级为一个int。有鉴于此,无符号移位通常已成为符号移位。 3.3.9 左移位运算符(<<) 左移位运算符(<<) 128 << 1 等于 128*21 = 256 16 <<2 等于 16*22 =64 运算符<<执行一个左移位。移位的结果是:第一个操作数乘以2的幂,指数的值是由第二个数给出的。例如: 128 << 1 gives 128*21 = 256 16<<2 gives 16*22 =64 3.3.10 类型转换 类型转换 如果赋值的信息丢失,程序员必须采用类型转换的方法确认赋值 在short和char之间的赋值需要一个显式转型 见3-16程序 在赋值的信息可能丢失的地方,编译器需要程序员用类型转换(typecast)的方法确认赋值。例如,它可以“挤压”一个long值到一个int变量中。显式转型做法如下: long bigValue =99L; int squashed =(int) (bigValue); 在上述程序中,期待的目标类型被放置在圆括号中,并被当作表达式的前缀,该表达式必须被更改。一般来讲,建议用圆括号将需要转型的全部表达式封闭。否则,转型操作的优先级可能引起问题。 注意──重温short的范围是:-215至215-1;char的范围是:0至215-1。 因而在short和char之间的赋值总需要一个显式转型
作者: starlight    时间: 2004-12-1 14:33     标题: SUN JAVA标准教程

3.3.11  升级和表达式的类型转换
升级和表达式的类型转换
-变量被自动升级为一个较长的形式(如:int至long的升级)
-如果变量类型至少和表达式类型一样大(位数相同),则表达式是赋值兼容的。
当没有信息丢失时,变量可被自动升级为一个较长的形式(如:int至long的升级)
    long bigval = 6; // 6 is an int type, OK
    int smallval = 99L; // 99L is a long, illegal
    double z = 12.414F; // 12.414F is float, OK
    float z1 = 12.414; // 12.414 is double, illegal
一般来讲,如果变量类型至少和表达式类型一样大(位数相同),则你可认为表达式是赋值兼容的。
对 + 运算符来说,当两个操作数是原始数据类型时,其结果至少有一个int,并且有一个通过提升操作数到结果类型、或通过提升结果至一个较宽类型操作数而计算的值,这可能会导致溢出或精度丢失。例如:
short  a,b,c
a=1;
b=2;
c= a+b;
上述程序会因为在操作short之前提升每个short至int而出错。然而,如果c被声明为一个int,或按如下操作进行类型转换:
    c = (short)(a+b);
则上述代码将会成功通过。
第四节  分支语句
分支语句
if, else语句
     if (布尔表达式){
        语句或块;
       }
     if (条件为真) {
        语句或块;
       }   else  {
        语句或块;
       }

条件语句使部分程序可根据某些表达式的值被有选择地执行。Java编程语言支持双路if和多路switch分支语句。
3.4.1  if, else语句
if, else语句的基本句法是:

     if (布尔表达式){
        语句或块;
       }  else  {
        语句或块;
       }
例:
int count;
   1.count = getCount(); // a method defined in the program
   2.if (count < 0) {
   3.System.out.println("Error: count value is negative.");
   4.}else {
   5.System.out.println("There will be " + count +
   6." people for lunch today.");
   7.}
在Java编程语言中,if ()用的是一个布尔表达式,而不是数字值,这一点与C/C++不同。前面已经讲过,布尔类型和数字类型不能相互转换。因而,如果出现下列情况:
if  (x)  // x is int
你应该使用下列语句替代:
if  (x ! = 0)
全部else部分是选择性的,并且当测试条件为假时如不需做任何事,else部分可被省略。
3.4.2  switch语句


分支语句
  switch语句
     switch语句的句法是:
     switch (expr1){
         case expr2:
         statements;
         break;
         case expr3:
         statements;
         break;
         default:
         statements;
         break;
      }

     switch语句的句法是:
     switch (expr1){
         case expr2:
         statements;
         break;
         case expr3:
         statements;
         break;
         default:
         statements;
         break;
      }
注意──在switch (expr1) 语句中,expr1必须与int类型是赋值兼容的;byte, short或char类型可被升级;不允许使用浮点或long表达式。

作者: starlight    时间: 2004-12-1 14:35     标题: SUN JAVA标准教程

当变量或表达式的值不能与任何case值相匹配时,可选缺省符(default)指出了应该执行的程序代码。如果没有break语句作为某一个case代码段的结束句,则程序的执行将继续到下一个case,而不检查case表达式的值。 例1: 1.switch (colorNum) { 2.case 0: 3.setBackground(Color.red); 4.break; 5.case 1: 6.setBackground(Color.green); 7.break; 8.default: 9.setBackground(Color.black); 10.break; 11.} 例2: 1.switch (colorNum) { 2.case 0: 3.setBackground(Color.red); 4.case 1: 5.setBackground(Color.green); 6.default: 7.setBackground(Color.black); 8.break; 9.} 例2设定背景颜色为黑色,而不考虑case变量colorNum的值。如果colorNum的值为0,背景颜色将首先被设定为红色,然后为绿色,再为黑色。 第五节 循环语句 循环语句 for语句 for (init_expr; boolean testexpr; alter_expr){ statement or block } 循环语句使语句或块的执行得以重复进行。Java编程语言支持三种循环构造类型:for, while和do loops。for和while循环是在执行循环体之前测试循环条件,而do loops是在执行完循环体之后测试循环条件。这就意味着for和while循环可能连一次循环体都未执行, 而do loops将至少执行一次循环体。 3.5.1 for循环 for循环的句法是: for (init_expr; boolean testexpr; alter_expr){ statement or block } 例如: for (int i = 0; i < 10; i++) { System.out.println("Are you finished yet?"); } System.out.println("Finally!"); 注意──Java编程语言允许在for () 循环结构中使用逗号作为分隔符。 例如,for (i= 0, j = 0; j<10; i++, j++)是合法的;它将i值初始化为零,并在每执行完一次循环体后,增加一次它们的值。 3.5.2 while循环 循环语句 while循环 while (布尔表达式) { 语句或块 } while循环的句法是: while (布尔表达式) { 语句或块 } 例如: int i = 0; while (i < 10) { System.out.println("Are you finished yet?"); i++; } System.out.println("Finally!"); 请确认循环控制变量在循环体被开始执行之前已被正确初始化,并确认循环控制变量是真时,循环体才开始执行。控制变量必须被正确更新以防止死循环。 3.5.3 do循环 循环语句 do/while语句 do { 语句或块; } while (布尔测试) do循环的句法是: do { 语句或块; } while (布尔测试) 例如: int i = 0; do { System.out.println("Are you finished yet?"); i++; } while (i < 10); System.out.println("Finally!"); 象while循环一样,请确认循环控制变量在循环体中被正确初始化和测试并被适时更新。 作为一种编程惯例,for循环一般用在那种循环次数事先可确定的情况,而while和do用在那种循环次数事先不可确定的情况。
作者: starlight    时间: 2004-12-1 14:36     标题: SUN JAVA标准教程

第六节  特殊循环流程控制

特殊循环流程控制
break [标注];
continue[标注];
label: 语句;// where statement must be any
               // legal statement.
下列语句可被用在更深层次的控制循环语句中:
break [标注];
continue[标注];
label: 语句;// where statement must be any
       // legal statement.
break语句被用来从switch语句、loop语句和预先给定了label的块中退出。
continue语句被用来略过并跳到循环体的结尾。
label可标识控制需要转换到的任何有效语句,它被用来标识循环构造的复合语句。
例如
loop: while (true) {
for (int i=0; i < 100; i++) {
switch (c = System.in.read()) {
case -1:
case ` \n ` :
// jumps out of while-loop to line #12
break loop;
....
}
} // end for
} // end while
test: for (...) {
....
while (...) {
if (j > 10) {
// jumps to the increment portion of
// for-loop at line #13
continue test;
}
} // end while
} // end for

练习:使用表达式
练习目标──你将编写、编译并运行两个使用标识符、表达式和控制结构的算法程序。
一、准备
为成功地完成本练习,你必须具备编译和运行Java程序的能力,并且熟悉流程控制构造。
二、任务
1级:创建一个阶乘应用程序
一个数X的阶乘(通常记作X!)等于X*(X-1)*(X-2)……*1。例如4!等于4×3×2×1=24。
创建一个称作Factor的应用程序,利用该应用程序可打印2,4,6和10的阶乘。
2级:求解一个几何题程序
已知一个直角三角形,其弦(最长边)的长度由下列公式给出:
编写一个称作hypotenuse的Java软件程序,从已知直角三角形的直角边计算最长边。
提示:从mod3/templates目录中提供的模板解决方案入手,从命令行输入;同时注意java.lang.Math类。
三、练习小结
    讨论──用几分钟的时间讨论一下在以上练习中你所获得的经验、感想和发现。
经验  解释  总结  应用
四、检查你的进度
   在进入下一模块之前,请确认你已经能够:
-区分实例变量和局部变量;
-描述实例变量是如何被初始化的;
-确认并更正“可能的赋值前的引用”的编译器错误;
-辨认、描述并使用Java软件运算符;
-区分合法和非法原始类型赋值;
-确认boolean表达式和它们在控制构造中的要求;
-辨认赋值兼容性和在基本类型中的必要转型;
-使用if, switch,for,while和do句型结构和break和continue的标注形式作为程序的流程控制结构。
五、思考题
-多数编程语言都使用什么数据类型来集合相似的数据元素?
-你怎样对一组元素进行相同的操作(如一个数组)?
-Java编程语言使用什么数据类型?

作者: starlight    时间: 2004-12-2 11:31     标题: SUN JAVA标准教程

第四章  数 组
本模块将描述Java编程语言中如何定义、初始化和使用数组。

第一节  相关问题
讨论──下列问题与本模块阐述的论题相关:
- 一个数组的用途是什么?
第二节目 标
完成本模块的学习后,你应该能够:
- 声明并创建原始数组、类数组或数组类型
- 解释为什么数组的元素需初始化
- 给出数组定义并初始化数组元素
- 确定一个数组中元素的数量
- 创建多维数组
- 编写从一个数组类型到另一个数组类型数组值的拷贝代码
第三节  数组的声明
声明数组
-相同类型的成组数据对象
-原始类型或类类型数组声明
-为一个引用创建空间
-数组是一个对象,而不是为原始类型储备的存储器

典型的数组是用来集合相同类型的对象并通过一个名称来引用这个集合。
你可以声明任何类型的数组──原始类型或类类型:
char s[ ];
Point p  ; // where point is a class
在Java编程语言中,即使数组是由原始类型构成,甚或带有其它类类型,数组也是一个对象。声明不能创建对象本身,而创建的是一个引用,该引用可被用来引用数组。数组元素使用的实际存储器可由new语句或数组初始化软件动态分配。
在以下部分,你将看到如何创建和初始化实际数组。
上述这种将方括号置于变量名之后的声明数组的格式,是用于C、C++和Java编程语言的标准格式。这种格式会使声明的格式复杂难懂,因而,Java编程语言允许一种替代的格式,该格式中的方括号位于变量名的左边:
char[ ]s;
Point[ ]p;
这样的结果是,你可以认为类型部分在左,而变量名在右。上述两种格式并存,你可选择一种你习惯的方式。声明不指出数组的实际大小。
注意----当数组声明的方括号在左边时,该方括号可应用于所有位于其右的变量

作者: starlight    时间: 2004-12-2 11:32     标题: SUN JAVA标准教程

第四节  创建数组

创建数组
     使用关键字new 创建一个数组对象
           s = new char 20;
           p = new Point 100;
           p0 = new Point();
           p1 = new Point();
            •
            •

     你可以象创建对象一样,使用关键字new 创建一个数组。
           s = new char 20;
           p = new Point 100;
     第一行创建了一个20个char值的数组,第二行创建了一个100个类型Point的变量。r然而,它并不创建100个Point对象;创建100个对象的工作必须分别完成如下:
           p0 = new Point();
           p1 = new Point();
        •
        •
        •
用来指示单个数组元素的下标必须总是从0开始,并保持在合法范围之内--大于0或等于0并小于数组长度。任何访问在上述界限之外的数组元素的企图都会引起运行时出错。下面还要谈到一些更好的数组初始化方法。
第五节  初始化数组
初始化数组
-初始化一个数组元素
-用初始化值创建一个数组
         String names  = 
            “Georgianna”,
            “Jen”,
            “Simon”,
           ;
当创建一个数组时,每个元素都被初始化。在上述char数组s的例子中,每个值都被初始化为0 (\u0000-null)字符;在数组p的例子中, 每个值都被初始化为null,表明它还未引用一个Point对象。在经过赋值 p0 = new Point()之后,数组的第一个元素引用为实际Point对象。
   
注意--所有变量的初始化(包括数组元素)是保证系统安全的基础,变量绝不能在未初始化状态使用。

    Java编程语言允许使用下列形式快速创建数组:
           String names  = 
            “Georgianna”,
            “Jen”,
            “Simon”,
           ;
其结果与下列代码等同:
           String names  ;
           names = new String 3;
           names 0 = “Georgianna”;
           names 1 = “Jen”;
           names 2 = “Simon”;
这种”速记”法可用在任何元素类型。例如:
       Myclass array  = 
         new Myclass (),
         new Myclass (),        
         new Myclass ()
        ;
适当的类类型的常数值也可被使用:
       Color palette   = 
           color.blue,
           color.red,
           color.white
        ;

作者: starlight    时间: 2004-12-2 11:32     标题: SUN JAVA标准教程

第六节  多维数组
多维数组
数组的数组
    int twoDim [][] = new int [4][];
    twoDim[0] = new int[5];
twoDim[1] = new int[5];
    int twoDim [][] = new int [][4]; 非法
每个数组有5个整数类型的4个数组的数组   
   int twoDim [][] = new int [4][5];
   twoDim[0] = new int[5];
   twoDim[1] = new int[5];
Java编程语言没有象其它语言那样提供多维数组。因为一个数组可被声明为具有任何基础类型,所以你可以创建数组的数组(和数组的数组的数组,等等)。一个二维数组如下例所示:
int twoDim [][] = new int [4][];
twoDim[0] = new int[5];
twoDim[1] = new int[5];
首次调用new而创建的对象是一个数组,它包含4个元素,每个元素对类型array of int的元素都是一个null引用并且必须将数组的每个点分别初始化。
注意-尽管声明的格式允许方括号在变量名左边或者右边,但此种灵活性不适用于数组句法的其它方面。例如: new int 4是非法的。

多维数组
非矩形数组的数组
twoDim0 = new int 2;
twoDim1 = new int 4;
twoDim2 = new int 6;
twoDim3 = new int 8;
每个数组有5个整数类型的4个数组的数组
    int twoDim   =  new int 45;

多维数组
因为这种对每个元素的分别初始化,所以有可能创建非矩形数组的数组。也就是说,twoDim的元素可按如下方式初始化:
twoDim0 = new int 2
twoDim1 = new int 4;
                  twoDim2 = new int 6;
                  twoDim3 = new int 8;
由于此种初始化的方法烦琐乏味,而且矩形数组的数组是最通用的形式,因而产生了一种”速记”方法来创建二维数组。例如:
            int twoDim   =  new int 45;
可被用来创建一个每个数组有5个整数类型的4个数组的数组。
第七节  数组界限
数组界限
     所有数组的下标都从0开始
            int list  = new int 10;
            for (int i= 0; i< list.length; i++)
              System.out.println(listi);
在Java编程语言中,所有数组的下标都从0开始。 一个数组中元素的数量被作为具有length属性的部分数组对象而存储; 这个值被用来检查所有运行时访问的界限。如果发生了一个越出界限的访问,那么运行时的报错也就出现了。
使用length属性的例子如下:
            int list  = new int 10;
            for (int i= 0; i< list.length; i++)
              System.out.println(listi);
使用length属性使得程序的维护变得更简单。

作者: starlight    时间: 2004-12-2 11:34     标题: SUN JAVA标准教程

第八节  拷贝数组

拷贝数组
-不能调整数组的大小
-可使用相同的引用变量来引用一个全新的数组
          int elements  = new int 6;
          elements = new int 10;
数组一旦创建后,其大小不可调整。然而,你可使用相同的引用变量来引用一个全新的数组:
          int myArray  = new int 6;
          myArray = new int 10;
    在这种情况下,第一个数组被有效地丢失,除非对它的其它引用保留在其它地方。
拷贝数组
            
拷贝数组

        System.arraycopy()方法
       // original array
   1.int myArray[] = { 1, 2, 3, 4, 5, 6 };
   2.
   3.// new larger array
   4.int hold[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
   5.// copy all of the myArray array to the hold
   6.// array, starting with the 0th index
   7.System.arraycopy(myArray, 0, hold, 0,
   8.myArray.length);

Java编程语言在System类中提供了一种特殊方法拷贝数组,该方法被称作arraycopy()。例如,araycopy可作如下使用:
// original array
   1.int myArray[] = { 1, 2, 3, 4, 5, 6 };
   2.
   3.// new larger array
   4.int hold[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
   5.// copy all of the myArray array to the hold
   6.// array, starting with the 0th index
   7.System.arraycopy(myArray, 0, hold, 0,
   8.myArray.length);
    在这一点,数组hold有如下内容:1,2,3,4,5,6,4,3,2,1。
注意—在处理对象数组时,System.arraycopy()拷贝的是引用,而不是对象。对象本身不改变。

练习:  使用数组
  练习目标--在定义并初始化数组后,你将在程序中使用数组。
一、准备
为成功地完成本练习,请务必理解基本的矩阵概念并了解如何定位一个数组以获取它的值。
二、任务
    1级:基本数组的使用
1. 创建一个称作BasicArray的类,在...main()方法中声明两个变量,一个是thisArray,另一个是thatArray,它们应属类型array of int。
2. 创建一个数组,它有10个int值,范围从1至10。分配这个第三数组的引用给变量thisArray。
3. 使用for()循环打印thisArray的所有值。如何控制循环的次数?
4. 编译并运行程序。多少值被打印?这些值是什么?
5. 对每个thisArray的元素,建立它的值为索引值的阶乘。打印数组的值。
6. 编译并运行程序。
7. 分配thisArray的引用给变量thatArray。打印thatArray的所有元素。
8. 编译并运行程序。tyatArray的多少值被显示?这些值是什么?它们来自何处。
9. 修改thisArray的某些元素,打印thatArray的值。
10. 编译并运行程序;在thatArray的值中,你注意到了什么?
11. 创建一个有20个int值的数组。分配新数组的引用给变量thatArray,打印thatArray的值。
12. 编译并运行程序。每个数组有多少值被显示? 这些值是什么?
13. 拷贝thisArray的值给thatArray。你将使用什么方法调用? 你将如何限制拷贝元素的数量? thatArray的元素10至19有什么变化?
14. 打印thatArray的值。
15. 编译并运行程序。你所显示的值都是正确的吗?如果不是,你知道有那些内容理解得不对吗?
16. 改变thatArray的某些值;打印thisArray和thatArray。
17. 编译并运行程序。这些值是你所期待的吗?
  2级:数组的数组
1. 创建一个称作Array2D的类,在main()方法中声明一个称作twoD的变量,它应属类型array of array of int。
2. 创建一个元素类型为int的数组,该数组应包括4个元素并被赋值到变量twoD的elements0。
3. 编写两个嵌套for()循环语句以打印twoD的全部值。以矩阵的格式安排输出 (可采用System.out.print()方法)。
4. 编译并运行程序。 你应该能发现此时出现了运行错误(空指针异常) ,这是因为twoD的elements1 至 3未被初始化。
5. 分别创建包括5个、6个和7个元素的int数组,将这些数组的引用分别赋予twoD的elements 1,2和3;确认完成上述操作的代码是在第3步所描述的嵌套for()循环之前插入的。
6. 编译并运行程序。这次你应该看到一个零值的非矩形布局。
7. 赋予twoD数组的每个元素一个明显的非零值(提示:使用Math.random() 以获得随机值)。
8. 声明一个属类型array of int的称作oneD的变量。然后, 创建一个包括4个元素的int数组。将该数组的引用分别赋予数组array twoD和oneD的第一个元素。赋值后,打印oneD和twoD数组。
9.编译并运行程序。请注意通过打印oneD的值而显示的单个数组与twoD数组的元素是相同的。
    3级:字谜游戏
1. 创建一个称作WordScrambler的应用程序,它具有一个词数组(长度最大为8个字符) ,用它可将一个词的字母拼凑(重排顺序) ,然后组成一个新词。
2.允许使用者看到词的拼凑过程,并分解5个游戏的运行过程。
三、练习小结
    讨论──用几分钟的时间讨论一下在以上练习中你所获得的经验、感想和发现。
经验  解释  总结  应用

四、检查你的进度
      在进入下一模块之前,请确认你已经能够:
- 声明并创建原始数组、类数组或数组类型
- 解释为什么数组的元素需初始化
- 给出数组定义并初始化数组元素
- 确定一个数组中元素的数量
- 创建多维数组
- 编写从一个数组类型到另一个数组类型数组值的拷贝代码
五、思考题
     你怎样创建一个三维数组?
     使用数组的缺点是什么?


作者: starlight    时间: 2004-12-3 16:43     标题: SUN JAVA标准教程

第五章  对象和类
本模块是Java编程语言中讨论面向对象语句及面向对象特征两部分中的第一部分。
第一节  相关问题
讨论—下面的问题与本模块中出现的材料相关:
-到目前为止学习的Java编程语言的元素存在于大部分语言中,不管它们是否是面向对象语言。
-Java编程语言拥有什么特征使它成为一个面向对象语言?
-“面向对象”这个术语真正的含义是什么?
第二节  目 标
学完本模块,你便能:
-定义封装、多态性以及继承
-使用private及public访问修饰符
-开发程序段创建并初始化一个对象
-对一个特殊对象调用一个方法  
-描述构造函数及方法重载
-描述this引用的用途
-讨论为什么Java应用程序代码是可重复使用的  
-在一个Java程序中,确认:
-package语句
-import语句
-类、成员函数以及变量
-构造函数  
-重载方法
-覆盖方法
-父类构造函数
   
第三节  对象基础
    面向对象程序(OOP)语句能使现实世界中的概念在计算机程序中变成模块。它包括构造程序的特征以及组织数据和算法的机制。OOP语言有三个特征:封装、多态性及继承。所有这些特征与类的概念是息息相关的。
5.3.1  抽象数据类型
    当数据类型是由数据项组成时,可以定义许多程序段或方法在该类型数据上专门运行。当程序语言定义一个基本类型如整数时,它同时也定义了许多运算方法(如加法、减法、乘法和除法),因而它可以在该类型的实例中运行。
在许多程序语言中,一旦一个集合数据类型已经定义,程序员定义应用函数在该类型的变量上运行,该变量在代码和集合类型(除非可能在命名规则中)之间无任何联系。
    有些程序语言,包括Java,允许在数据类型的声明和操作该类型变量的代码的声明之间有紧密的联系。这种联系通常被称为抽象数据类型。

作者: starlight    时间: 2004-12-3 16:44     标题: SUN JAVA标准教程

5.3.2  类和对象
    Java编程语言中的抽象数据类型概念被认为是class。类给对象的特殊类型提供定义。它规定对象内部的数据,创建该对象的特性,以及对象在其自己的数据上运行的功能。因此类就是一块模板。Objects是在其类模块上建立起来的,很象根据建筑图纸来建楼。同样的图纸可用来建许多楼房,而每栋楼房是它自己的一个对象。
    应该注意,类定义了对象是什么,但它本身不是一个对象。在程序中只能有类定义的一个副本,但可以有几个对象作为该类的实例。在Java编程语言中使用new运算符实例化一个对象。
    在类中定义的数据类型用途不大,除非有目的地使用它们。方法定义了可以在对象上进行的操作,换言之,方法定义类来干什么。因此Java编程语言中的所有方法都属于一类。不象C++程序,Java软件程序不可能在类之外的全局区域有方法。
看一个类的例子:
    class EmpInfo {
       String name;
       String designation;
       String department;
     }
    这些变量(name, designation和department)被称为类EmpInfo的成员。
实例化一个对象,创建它,然后如下所述对其成员赋值:
      EmpInfo employee = new EmpInfo();  //creates instance
      employee.name = Robert Javaman ";   // initializes
      employee.designation = " Manager " ;  // the three
      employee.department = " Coffee Shop " ;  // members
EmpInfo类中的employee对象现在就可以用了。例如:
     System.out.println(employee.name + " is " +
        employee.designation + " at " +
        employee.department);
打印结果如下:
     Robert Javaman is Manager at Coffee Shop
   如下所述,现在可以在类中放入方法print( )来打印数据了。数据和代码可以封装在一个单个实体中,这是面向对象语言的一个基本特征。定名为print( )的代码段可以被作为一个方法而调用,它是术语“函数”的面向对象的称法。
class EmpInfo {
   String name;
   String designation;
   String department;
   void print() {
        System.out.println(name + " is " + designation + " at " + department);
   }
}
    一旦对象被创建并被实例化,该方法就打印出类成员的数据。按下述步骤实现:
     EmpInfo employee = new EmpInfo(); // creates instance
     employee.name = " Robert Javaman " ; // initializes
     employee.designation = " Manager " ; // the three
     employee.department = " Coffee Shop " ; // members
     employee.print();// prints the details
    看看集合数据类型MyDate 和对下一个日期赋值的函数tomorrow( )。
    按如下所述在MyDate类型和tomorrow( )方法之间创建一种联系:
     public class MyDate {
        private int day, month, year;
        public void tomorrow() {
          // code to increment day
       }
     }
注—本声明中的“private”一词将在后文描述。         
方法不是(作为分离的实体)在数据上运行,而数据(作为对象的一部分)对它本身进行操作。
     MyDate d = new MyDate();
     d.tomorrow();
    这个注释表明行为是由对象而不是在对象上完成的。记住,可以用点记号来指向MyDate类中的字段。
    这就意味着“MyDate对象的day字段由变量d.调用。于是,前面的例子“MyDate对象的tomorrow行为由变量d.调用” ,换言之,就是d对象对它本身进行tomorrow()运算。
    方法是一个对象的属性并且能作为单个单元的一部分与它所在对象的数据发生密切的相互作用,这个是一个关键的面向对象的概念。(如果与这个概念不同,即,方法是分离的实体,从外部引入,作用在数据上。)message passing(消息传递)这个术语通常用来表达这样一个概念,即:指示一个对象在它本身数据上做某项工作,一个对象的方法定义了该对象能在它本身数据上做什么。

作者: starlight    时间: 2004-12-3 16:45     标题: SUN JAVA标准教程

5.3.3 定义方法 定义方法 方法声明采取这样的格式: ([]) [throws ] {} public void addDays(int days) { } Java编程语言使用一种与其它语言,尤其是C和C++,非常相似的办法来定义方法。其声明采用以下格式: ([]) [throws ] {} 可以是任何合法标识符,并带有用已经使用的名称为基础的某些限制条件。 表示方法返回值的类型。如果方法不返回任何值,它必须声明为void(空)。Java技术对返回值是很严格的,例如,如果声明某方法返回一个int值,那么方法必须从所有可能的返回路径中返回一个int(只能在等待返回该int值的上下文中被调用。) 段能承载许多不同的修饰符,包括公共的、受保护的,以及私有的。公共访问修饰符表示方法可以从任何其它代码调用。私有表示方法只可以由该类中的其它方法来调用。受保护将在以后的课程中讨论。 允许将参数值传递到方法中。列举的元素由逗号分开,而每一个元素包含一个类型和一个标识符。 throws 子句导致一个运行时错误(异常)被报告到调用的方法中,以便以合适的方式处理它。非正常的情况在中有规定。 例如: public void addDays(int days) { } 告诉方法的本体,用,来接受表示将天数增加到当前日期中的那个参数。 在这种方法中,值是以标识符days来引用的。 5.3.4 值传递 值传递 Java编程语言只由值传递参数 当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。 对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。 Java编程语言只由值传递参数,也就是说,参数不能由被调用的方法来改变。当一个对象实例作为一个参数传递到方法中时,参数的值就是对象的引用。对象的内容可以在被调用的方法中改变,但对象引用是永远不会改变的。 下面的代码例子可以阐明这一点: 1 public class PassTest { 2 3float ptValue; 4 5// Methods to change the current values 6public void changeInt (int value) { 7value = 55; 8} 9 10public void changeStr (String value) { 11value = new String ( " different " ); 12} 13 14public void changeObjValue (PassTest ref) { 15ref.ptValue = 99.0f; 16} 17 18public static void main (String args[]) { 19 20String str; 21int val; 22 23// Create an instance of the class 24 25PassTest pt = new PassTest (); 26// Assign the int 27val = 11; 28 29// Try to change it 30pt.changeInt (val); 31 32// What is the current value? 33System.out.println ( " Int value is: " + val); 34 35// Assign the string 36str = new String ( " hello " ); 37 38// Try to change it 39pt.changeStr (str); 40 41// What is the current value? 42System.out.println ( " Str value is: " + str); 43 44// Now set the ptValue 45pt.ptValue = 101.0f; 46 47 48// Now change the value of the float 49// through the object reference 50pt.changeObjValue (pt); 51 52// What is the current value? 53System.out.println ( " Current ptValue is: " + 54 pt.ptValue); 55 } 56} 这个代码输出如下内容: c:\student\source\> java PassTest Int value is: 11 Str value is: hello Current ptValue is: 99.0 字符串对象是不会被changeStr()改变的,但是,PassTest对象的内容被改变了。
作者: starlight    时间: 2004-12-3 16:46     标题: SUN JAVA标准教程

5.3.5  this引用
this引用
public class MyDate {
  private int day, month, year;
  public void tomorrow() {
    this.day = this.day + 1;
    // wrap around code...
  }
}
    关键字this是用来指向当前对象或类实例的。这里,this.day指的是当前对象的day字段。
public class MyDate {
  private int day, month, year;
  public void tomorrow() {
    this.day = this.day + 1;
    // wrap around code...
  }
}
    Java编程语言自动将所有实例变量和方法引用与this关键字联系在一起,因此,使用关键字在某些情况下是多余的。下面的代码与前面的代码是等同的。
public class MyDate {
  private int day, month, year;
  public void tomorrow() {
    day = day + 1; // no ` this. ' before ` day '
    // wrap around code...
  }
}
  也有关键字this使用不多余的情况。如,需要在某些完全分离的类中调用一个方法并将当前对象的一个引用作为参数传递时。例如:
Birthday bDay = new Birthday (this);
5.3.6  数据隐藏
数据隐藏
public class Date {
  private int day, month, year;
  pubic void tomorrow(){
    this.day = this.day +1;
    // wrap around code…
  }
}
public class DateUser {
  public static void main(String args[]) {
    Date mydate = new MyDate ();
    Mydate.day = 21; //illegal!
  }
}
在MyDate 类的day,month,year声明中使用关键字private,使从除了在MyDate类本身的方法以外的任何代码中访问这些成员成为不可能。因此,给MyDate类指定一个声明,下述代码是非法的:
public class DateUser {
  public static void main(String args[]) {
    MyDate d = new MyDate ();
    d.day = 21; // illegal!
  }
}
   防止直接访问数据变量看起来奇怪,但它实际上对使用MyDate类的程序的质量有极大的好处。既然数据的单个项是不可访问的,那么唯一的办法就是通过方法来读或写。因此,如果要求类成员的内部一致性,就可以通过类本身的方法来处理。
    思考一下允许从外部对其成员进行自由访问的MyDate类。代码做如下工作将是非常容易的:
MyDate d = new MyDate ();
d.day = 32; // invalid day
d.month = 2; d.day = 30; // plausible but wrong
d.month = d.month + 1; // omit check for wrap round
   
警告—这些和其它类似的赋值导致了在MyDate对象字段中无效的或不一致的值。这种情形是不可能马上作为问题暴露出来的,但肯定会在某个阶段终止程序。
    如果类的数据成员没有暴露(被封装在类里),那么,类的用户会被迫使用方法来修改成员变量。这些方法能进行有效性检查。考虑将下述方法作为MyDate类的一个部分。
public void setDay(int targetDay) {
  if (targetDay > this.daysInMonth()) {
    System.err.println( " invalid day " + targetDay);
  }
  else {
    this.day = targetDay;
  }
}
方法检查就是要看所要求设定的日期是否有效。如果日期无效,方法忽略了请求并打印出了信息。后面将会看到Java编程语言提供一个更有效的机制来处理溢出的方法参数。 但现在,你可以看到Date类对无效日期是受到有效保护的。
注—在上例中,daysInMonth()被指定为Date类中的一个方法。因此,它有一个this值,从这个值上,它可以提取回答询问所要求的month和 year。由于与成员变量一起使用,daysInMonth()方法的this的使用就多余了。
关于如何正确地调用方法,诸如“参数“月份”的值在对象中必须在有效范围内”的规则被叫做不变量(或前置和后置条件)。谨慎使用前置条件测试,可使类更容易再次使用,而且在重用中更可靠,因为如果任何方法被误用,使用该类的程序员能马上发现。

作者: starlight    时间: 2004-12-3 16:46     标题: SUN JAVA标准教程

5.3.7  封装
封装
    隐藏类的实现细节
    迫使用户去使用一个界面去访问数据
    使代码更好维护
    除了保护对象的数据不被误修改外,在确保所要求的副作用被正确处理的情况下,迫使用户通过方法访问数据能使类的重用变得更简单。比如,在MyDate类的情形之下,考虑如何构造tomorrow()方法。
如果数据完全可以访问,那么类的每一个用户都需要增加day的值,测试当前月份的天数,并处理月终(而且可能是年终)情形。这就毫无意义而且容易出错。仅管这些要求对日期来说是很好理解的,其它数据类型可能具有鲜为人知的相似的限制。通过迫使类的用户去使用所提供的tomorrow()方法,保证每个人每次都能连续地并且正确地处理必要的副作用。
数据隐藏通常指的就是封装。它将类的外部界面与类的实现区分开来,隐藏实现细节。迫使用户去使用外部界面,即使实现细节改变,还可通过界面承担其功能而保留原样,确保调用它的代码还继续工作。这使代码维护更简单。
第四节  重载方法名称
重载方法名称
    它可如下所示使用:
           public void println(int i)
           public void println(float f)
           public void println()
参数表必须不同
返回类型可以不同
    在某些情况下,可能要在同一个类中写几种做同样工作但带有不同参数的方法。考虑一个简单方法,它试图输出参数的文本表示法。这种方法被称做println()。
    现在假设打印每个int,float,String类型需要不同的打印方法。这是合情合理的,因为各种数据类型要求不同的格式,而且可能要求不同的处理。可以分别创建三种方法,即:printInt(),printfloat()和printString()。但这是很乏味的。
    Java与其它几种编程语言一样,允许对不止一种方法重用方法名称。清楚地说,只有当某种东西能区分实际上需要哪种方法并去调用它时,它才能起作用。在三种打印方法的情况下,可能在参数的数量和类型的基础上对此进行区分。
    通过重用方法名称,可用下述方法结束:
public void println(int i)
public void println(float f)
public void println()
    当写代码来调用这些方法中的一种方法时,根据提供的参数的类型选择合适的一种方法。
    有两个规则适用于重载方法:
    调用语句的参数表必须有足够的不同,以至于允许区分出正确的方法被调用。正常的拓展晋升(如,单精度类型float到双精度类型double)可能被应用,但是这样会导致在某些条件下的混淆。
    方法的返回类型可以各不相同,但它不足以使返回类型变成唯一的差异。重载方法的参数表必须不同。
第五节  构造并初始化对象
构造并初始化对象
调用new XXX()来为新对象分配空间会产生如下结果:
    新对象的空间被分配并被初始化为0或空值
    进行了显式的初始化
    构造函数被执行
    已经看到,为了给新对象分配空间,如何必须执行调用到new XXX()。有时还会看到参数被放在括号中,如:new Button (“press me”)。使用关键字new会导致下述情况:
    首先,新对象的空间被分配并初始化到0或空值。在Java编程语言中,该阶段是不可分的,以确保在分配空间的过程中不会有大小为随机值的对象。
    其次,进行显式的初始化。
    第三,构造函数被执行,它是一种特殊方法。括号中传递给new的参数被传递给构造函数。
本节讨论这最后两个步骤。
5.5.1  显式成员初始化
显式成员初始化
public class Initialized {
  private int x = 5;
  private String name = " Fred " ;
  private Date created = new Date();
  // Methods go here
  ...
}
  如果将简单的赋值表达式放在成员声明中,在对象构造过程中会进行显式成员初始化。
public class Initialized {
  private int x = 5;
  private String name = " Fred " ;
  private Date created = new Date();
// Methods go here
...
}
5.5.2  构造函数
构造函数
方法名称必须完全与类名称相匹配
对于方法,不要声明返回类型
    刚刚描述过的显式初始化机制为在一个对象中设定字段的初始值提供了一个简单的办法。但有时确实需要执行一个方法来进行初始化。也许还需要处理可能发生的错误。或者想用循环或条件表达式来进行初始化。或者想把参数传递到构造过程中以便要求构造新对象的代码能控制它创建的对象。
    一个新对象的初始化的最终步骤是去调用一个叫做构造函数的方法。
    构造函数是由下面两个规则所确认的:
    方法名称必须与类名称完全相匹配。
    对于方法,不要声明返回类型
构造函数
public class Xyz {
  // member variables go there
public Xyz() {
  // set up the object.
    }
public Xyz(int x) {
// set up the object with a parameter
    }
}
public class Xyz {
  // member variables
  public Xyz() {               // No-arg constructor
  // set up the object.
  }
  public Xyz(int x) {           //int-arg constructor
    // set up the object using the parameter x.
  }
}
注—由于采用了方法,因此可以通过为几个构造函数提供不同的参数表的办法来重载构造函数。当发出new Xyz(argument_list)调用的时候,传递到new语句中的参数表决定采用哪个构造函数。                                          

作者: starlight    时间: 2004-12-3 16:47     标题: SUN JAVA标准教程

5.5.3  调用重载构造函数
调用重载构造函数
public class Employee {
  private String name;
  private int salary;
public Employee(String n, int s) {
  name = n;
  salary = s;
}
public Employee(String n) {
  this(n, 0);
}
  public Employee() {
    this( " Unknown " );
  }
}
    如果有一个类带有几个构造函数,那么也许会想复制其中一个构造函数的某方面效果到另一个构造函数中。可以通过使用关键字this作为一个方法调用来达到这个目的。
public class Employee {
private String name;
private int salary;
public Employee(String n, int s) {
  name = n;
  salary = s;
}
public Employee(String n) {
  this(n, 0);
}
public Employee() {
  this( " Unknown " );
}
}
    在第二个构造函数中,有一个字符串参数,调用this(n,0)将控制权传递到构造函数的另一个版本,即采用了一个String参数和一个int参数的构造函数中。
在第三个构造函数中,它没有参数,调用this(“Unknownn”)将控制权传递到构造函数的另一个版本,即采用了一个String参数的构造函数中。
注—对于this的任何调用,如果出现,在任何构造函数中必须是第一个语句。
5.5.4  缺省构造函数
缺省构造函数
    每个类中都有
    能够用new Xxx()创建对象实例
如果增加一个带参数的构造函数声明,将会使缺省无效
    每个类至少有一个构造函数。如果不写一个构造函数,Java编程语言将提供一个。该构造函数没有参数,而且函数体为空。
缺省构造函数能用new Xxx()创建对象实例,反之,你会被要求为每个类提供一个构造函数。
注—如果增加一个带参数的构造函数声明到一个类中,该类以前没有显式构造函数,那么将失去该缺省构造函数。基于这一点,对new Xxx()的调用将会引起编译错误。认识到这一点很重要。

作者: starlight    时间: 2004-12-3 16:47     标题: SUN JAVA标准教程

第六节  子 类
5.6.1  is a 关系
Is a 关系
    Employee类
         public class Employee {
             String name;
             Date hireDate;
             Date dateOfBirth;
         }
    在编程中,常常要创建某件事的模型(如:一个职员),然后需要一个该基本模型的更专业化的版本。比如,可能需要一个经理的模型。显然经理实际上是一个职员,只是一个带有附加特征的职员。
    看看下面的例子中类声明所阐述的:
public class Employee {
    String name;
    Date hireDate;
    Date dateOfBirth;
    String jobTitle;
    int grade;
    ...
}
这个例子阐述了在Manager和Employee类之间的数据复制。此外,还可能有许多适用于 Employee和 Manager两者的方法。因此,需要有一种办法从现有类来创建一个新类。这就叫做子类。
5.6.2  Extends关键字
Extends关键字
public class Employee {
  String name;
  Date hireDate;
  Date dateOfBirth;
  String jobTitle;
  int grade;
  ...
}
public class Manager extends Employee {
  String department;
  Employee [] subordinates;
}
  在面向对象的语言中,提供了特殊的机制,允许程序员用以前定义的类来定义一个类。如下所示,可用关键字extends来实现:
public class Employee {
  String name;
  Date hireDate;
  Date dateOfBirth;
  String jobTitle;
  int grade;
  ...
}
public class Manager extends Employee {
  String department;
  Employee [] subordinates;
  ...
}
在这样的安排中,Manager类被定义,具有 Employee 所拥有的所有变量及方法。所有这些变量和方法都是从父类的定义中继承来的。所有的程序员需要做的是定义额外特征或规定将适用的变化。
注--这种方法是在维护和可靠性方面的一个伟大进步。如果在Employee类中进行修改,那么, Manager类就会自动修改,而不需要程序员做任何工作,除了对它进行编译。

注—对一个继承的方法或变量的描述只存在于对该成员进行定义的类的API文档中。当浏览探索一个(子)类的时候,一定要检查父类和其它祖先类中的继承成员。

5.6.3  参数和异类收集
参数和异类收集
    具有共同点的类的收集被称做同类收集,如:数组
    具有不同对象的收集叫异类收集,如:从各种其它类继承的类的收集
    可以创建具有共同类的对象的收集(如数组)。这种收集被称作同类收集。
    Java编程语言有一个对象类,因此,由于多态性,它能收集所有种类的元素,正如所有类都扩展类对象一样。这种收集被称作异类收集。
    创建一个Manager并慎重地将其引用赋到类型Employee的变量中似乎是不现实的。但这是可能的,而且有很多为什么要取得这种效果的理由。
    用这种方法,可以写出一个能接受通用对象的方法,在这种情况下,就是类Employee,并在它的任何子类的对象上正确地运作。然后可以在应用类中产生一个方法,该应用类抽取一个职员,并将它的薪水与某个阈值进行比较来决定该职员的纳税责任。利用多态性,可以做到这些:
// In the Employee class
public TaxRate findTaxRate(Employee e) {
  // do calculations and return a tax rate for e
}
// Meanwhile, elsewhere in the application class
Manager m = new Manager();
:
TaxRate t = findTaxRate(m);
    这是合法的,因为一个经理就是一个职员。
    异类收集就是不相似的东西的收集。在面向对象语言中,可以创建许多东西的收集。所有的都有一个共同的祖先类-Object类。如:
Employee [] staff = new Employee[1024];
staff[0] = new Manager();
staff[1] = new Employee();
甚至可以写出一个排序的方法,它将职员按年龄或薪水排序,而忽略其中一些人可能是经理。
注-每个类都是Object的一个子类,因此,可以用Object数组作为任何对象的容器。唯一不能被增加到Object数组中的唯一的东西就是基本变量(以及包装类,将在模块6中讨论,请注意这一点)。比Object数组更好的是向量类,它是设计来贮存异类收集对象的。

作者: starlight    时间: 2004-12-3 16:49     标题: SUN JAVA标准教程

5.6.4  单继承性
单继承性
当一个类从一个唯一的类继承时,被称做单继承性。单继承性使代码更可靠。界面提供多继承性的好处,而且没有(多继承的)缺点。
    Java编程语言允许一个类仅能扩展成一个其它类。这个限制被称做单继承性。单继承性与多继承性的优点是面向对象程序员之间广泛讨论的话题。Java编程语言加强了单继承性限制而使代码更为可靠,尽管这样有时会增加程序员的工作。模块6讨论一个被叫做界面(Interface)的语言特征,它允许多继承性的大部分好处,而不受其缺点的影响。
    使用继承性的子类的一个例子如图5-1所示:



图5-1      继承
5.6.5  构造函数不能被继承
构造函数不能被继承
子类从超类(父类)继承所有方法和变量
子类不从超类继承构造函数
包含构造函数的两个办法是
    使用缺省构造函数
    写一个或多个显式构造函数
    尽管一个子类从父类继承所有的方法和变量,但它不继承构造函数,掌握这一点很重要。
一个类能得到构造函数,只有两个办法。或者写构造函数,或者根本没有写构造函数,类有一个缺省构造函数。
注-除了子构造函数外,父类构造函数也总是被访问。这将在后面的模块中详细讨论。
5.6.6  多态性
多态性
    有能力拥有有许多不同的格式,就叫做多态性。比如,经理类能访问职员类方法。
    一个对象只有一个格式
    一个变量有许多格式,它能指向不同格式的对象
    将经理描述成职员不只是描述这两个类之间的关系的一个简便方法。回想一下,经理类具有父类职员类的所有属性、成员和方法。这就是说,任何在Employee上的合法操作在Manager上也合法。如果Employee 有raiseSalary()和fire()两个方法,那么Manager 类也有。
一个对象只有一个格式(是在构造时给它的)。但是,既然变量能指向不同格式的对象,那么变量就是多态性的。在Java编程语言中,有一个类,它是其它所有类的父类。这就是java.lang.object类。因此,实际上,以前的定义被简略为:
public class Employee extends Object and
public class Manager extends Employee
    Object类定义许多有用的方法,包括toString(),它就是为什么Java软件中每样东西都能转换成字符串表示法的原因。(即使这仅具有有限的用途)。
    象大多数面向对象语言一样,Java实际上允许引用一个带有变量的对象,这个变量是父类类型中的一个。因此,可以说:
Employee e = new Manager()
    使用变量e是因为,你能访问的对象部分只是Employee的一个部分;Manager的特殊部分是隐藏的。这是因为编译者应意识到,e 是一个Employee,而不是一个Manager。因而,下述情况是不允许的:
e.department = " Finance " ; // illegal
注-多态性是个运行时问题,与重载相反,重载是一个编译时问题。
5.6.7  关键字super
关键字super
    super被用在类中引用其超类。
    super被用来调用超类的成员变量。
    超类行为就被调用,就好象对象是超类的组件。
    调用行为不必发生在超类中,它能自动向上层类追溯。
    关键字super可被用来引用该类中的超类。它被用来引用超类的成员变量或方法。
    通常当覆盖一个方法时,实际目的不是要更换现有的行为,而是要在某种程度上扩展该行为。
    用关键字super 可获得:
public class Employee {
  private String name;
  private int salary;
public String getDetails() {
  return Name: " + name + "\nSalary: " + salary;
  }
}
public class Manager extends Employee {
  private String department;
  public String getDetails() {
    return super.getDetails() + // call parents'
                         // method
      "\nDepartment: " + department;
  }
}
    请注意,super.method()格式的调用,如果对象已经具有父类类型,那么它的方法的整个行为都将被调用,也包括其所有副面效果。该方法不必在父类中定义。它也可以从某些祖先类中继承。
5.6.8  Instanceof 运算符
Instanceof  运算符
public class Employee extends Object
public class Manager extends Employee
public class Contractor extends Employee
public void method(Employee e) {
  if (e instanceof Manager) {
    // Get benefits and options along with salary
  }else if (e instanceof Contractor) {
    // Get hourly rates
  }else {
    // temporary employee
  }
}
    假如能使用引用将对象传递到它们的父类中,那么有时你想知道实际有什么,这就是instanceof运算符的目的。假设类层次被扩展,那么你就能得到:
public class Employee extends Object
public class Manager extends Employee
public class Contractor extends Employee
注—记住,在可接受时, extends Object 实际上是多余的。在这里它仅作为一个提示项。
    如果通过Employee类型的引用接受一个对象,它变不变成Manager或Contractor都可以。可以象这样用instanceof 来测试:
public void method(Employee e) {
  if (e instanceof Manager) {
    // Get benefits and options along with salary
  }else if (e instanceof Contractor) {
    // Get hourly rates
  }else {
    // regular employee
  }
}
注—在C++中,可以用RTTI(运行时类型信息)来做相似的事,但在Java编程语言中的instanceof功能更强大。

作者: starlight    时间: 2004-12-3 16:50     标题: SUN JAVA标准教程

5.6.9  对象的类型转换
对象的类型转换
    使用instanceof来测试一个对象的类型。
    用类型转换来恢复一个对象的全部功能。
    用下述提示来检查类型转换的正确性:
  向上的类型转换是隐含地实现的。
  向下的类型转换必须针对子类并由编译器检查。
    当运行时错误发生时,运行时检查引用类型。
    在你接收父类的一个引用时,你可以通过使用Instanceof运算符判定该对象实际上是你所要的子类,并可以用类型转换该引用的办法来恢复对象的全部功能。
public void method(Employee e) {
  if (e instanceof Manager) {
    Manager m = (Manager)e;
    System.out.println( " This is the manager of " + m.department);
  }
  // rest of operation
}
    如果不用强制类型转换,那么引用e.department的尝试就会失败,因为编译器不能将被称做department的成员定位在Employee类中。
    如果不用instanceof做测试,就会有类型转换失败的危险。通常情况下,类型转换一个对象引用的尝试是要经过几种检查的:
    向上强制类型转换类层次总是允许的,而且事实上不需要强制类型转换运算符。可由简单的赋值实现。
    对于向下类型转换,编译器必须满足类型转换至少是可能的这样的条件。比如,任何将Manager引用类型转换成Contractor引用的尝试是肯定不允许的,因为Contractor不是一个Manager。类型转换发生的类必须是当前引用类型的子类。
    如果编译器允许类型转换,那么,该引用类型就会在运行时被检查。比如,如果instanceof检查从源程序中被省略,而被类型转换的对象实际上不是它应被类型转换进去的类型,那么,就会发生一个运行时错误(exception)。异常是运行时错误的一种形式,而且是后面模块中的主题。
第七节  覆盖方法
覆盖方法
    子类可以修改从父类继承来的行为
子类能创建一个与父类方法有不同功能的方法,但具有相同的
    名称
  返回类型
         参数表
    除了能用附加额外特征的办法在旧类基础上产生一个新类,它还可以修改父类的当前行为。
    如果在新类中定义一个方法,其名称、返回类型及参数表正好与父类中方法的名称、返回类型及参数相匹配,那么,新方法被称做覆盖旧方法。
注—记住,在同类中具有相同名称不同参数表的方法是被简单覆盖。这导致编译器使用所提供的参数来决定调用哪个方法。
    考虑一下在Employee和Manager类中的这些方法的例子:
public class Employee {
  String name;
  int salary;
  public String getDetails() {
    return " Name: " + name + " \n " +
       "Salary: " + salary;
  }
}
public class Manager extends Employee {
  String department;
  public String getDetails() {
    return " Name: " + name + " \n " +
         " Manager of " + department;
  }
}
Manager类有一个定义的getDetails()方法,因为它是从Employee类中继承的。基本的方法被子类的版本所代替或覆盖了。
覆盖方法
    虚拟方法调用
           Employee e = new Manager();
           e.getDetails();
    编译时类型与运行时类型  
假设第121页上的例子及下述方案是正确的:
Employee e = new Employee();
Manager m = new Manager();
   如果请求e.getDetails()和m.getDetails,就会调用不同的行为。Employee对象将执行与Employee有关的getDetails版本,Manager对象将执行与Manager有关的getDetails()版本。
   不明显的是如下所示:
Employee e = new Manager();
e.getDetails();
    或某些相似效果,比如一个通用方法参数或一个来自异类集合的项。
    事实上,你得到与变量的运行时类型(即,变量所引用的对象的类型)相关的行为,而不是与变量的编译时类型相关的行为。这是面向对象语言的一个重要特征。它也是多态性的一个特征,并通常被称作虚拟方法调用。
    在前例中,被执行的e.getDetails()方法来自对象的真实类型,Manager。
注—如果你是C++程序员,就会在Java编程语言和C++之间得出一个重要的区别。在C++中,你要想得到该行为,只能在源程序中将方法标记成virtual。然而,在纯面向对象语言中,这是不正常的。当然,C++这么做是要提高执行速度。

作者: starlight    时间: 2004-12-3 16:51     标题: SUN JAVA标准教程

第八节  调用覆盖方法
覆盖方法的规则
    必须有一个与它所覆盖的方法相同的返回类型
    不能比它所覆盖的方法访问性差
    不能比它所覆盖的方法抛出更多的异常。
覆盖方法的规则
    记住,子方法的名称以及子方法参数的顺序必须与父类中的方法的名称以及参数的顺序相同以便该方法覆盖父类版本。下述规则适用于覆盖方法:
    覆盖方法的返回类型必须与它所覆盖的方法相同。
覆盖方法不能比它所覆盖的方法访问性差
覆盖方法不能比它所覆盖的方法抛出更多的异常。(异常将在下一个模块中讨论。)
    这些规则源自多态性的属性和Java编程语言必须保证“类型安全”的需要。考虑一下这个无效方案:
public class Parent {
  public void method() {
  }
}
public class Child extends Parent {
  private void method() {
  }
}
public class UseBoth {
  public void otherMethod() {
    Parent p1 = new Parent();
    Parent p2 = new Child();
    p1.method();
    p2.method();
  }
}
Java编程语言语义规定,p2.method()导致方法的Child版本被执行,但因为方法被声明为private,p2(声明为Parent)不能访问它。于是,语言语义冲突。
第九节  调用父类构造函数
调用父类构造函数
    对象的初始化是非常结构化的。
    当一个对象被初始化时,下述行为按顺序发生:
    存储空间被分配并初始化到0值
    层次中的每个类都进行显式初始化
    层次中的每个类都调用构造函数
    在Java编程语言中,对象的初始化是非常结构化的。这样做是要保证安全。在前面的模块中,看到了当一个特定对象被创建的实例时发生了什么。由于继承性,图象被完成,而且下述行为按顺序发生:
    存储空间被分配并初始化到0值
    进行显式初始化
        调用构造函数
    层次中的每个类都会发生最后两个步骤,从最上层开始。
    Java技术安全模式要求在子类执行任何东西之前,描述父类的一个对象的各个方面都必须初始化。因此,Java编程语言总是在执行子构造函数前调用父类构造函数的版本。
调用父类构造函数
    在许多情况下,使用缺省构造函数来对父类对象进行初始化。
public class Employee {
  String name;
  public Employee(String n) {
    name = n;
  }
}
public class Manager extends Employee {
  String department;
  public Manager(String s, String d) {
    super(s);
    department = d;
  }
}

    无论是super还是this,都必须放在构造函数的第一行
调用父类构造函数
通常要定义一个带参数的构造函数,并要使用这些参数来控制一个对象的父类部分的构造。可能通过从子类构造函数的第一行调用关键字super的手段调用一个特殊的父类构造函数作为子类初始化的一部分。要控制具体的构造函数的调用,必须给super()提供合适的参数。当不调用带参数的super时,缺省的父类构造函数(即,带0个参数的构造函数)被隐含地调用。在这种情况下,如果没有缺省的父类构造函数,将导致编译错误。
public class Employee {
  String name;
  public Employee(String n) {
    name = n;
  }
}
public class Manager extends Employee {
  String department;
  public Manager(String s, String d) {
    super(s); // Call parent constructor
           // with String argument
  department = d;
  }
}
注—调用super()能将任意数量的合适的参数赋到父类中的不同构造函数中,但它必须是构造函数中的第一个语句。
    当被使用时,super或this必须被放在构造函数的第一行。显然,两者不能被放在一个单独行中,但这种情况事实上不是一个问题。如果写一个构造函数,它既没有调用super(…)也没有调用this(…),编译器自动插入一个调用到父类构造函数中,而不带参数。其它构造函数也能调用super(…)或this(…),调用一个Static方法和构造函数的数据链。最终发生的是父类构造函数(可能几个)将在链中的任何子类构造函数前执行。
第十节  编组类
5.10.1  包

    包声明必须在源程序文件的开始被声明
    根据源程序文件,只允许有一个包声明
           // Class Employee of the Finance department for the
           // ABC company
           package abc.financedept;
           public class Employee {
           ...
           }
   包名称是分层的,由圆点隔开
    Java编程语言提供package机制作为把相关类组成组的途径。迄今为止,所有的这些例子都属于缺省或未命名包。
    可以用package语句表明在源程序文件中类属于一个特殊的包。
           // Class Employee of the Finance department for the
           // ABC company
           package abc.financedept;
           public class Employee {
           ...
           }
    包声明,如果有的话,必须在源程序文件的开始处。可以以空白和注解开始,而没有其它方式。只允许有一个包声明并且它控制整个源程序文件。
包名称是分层的,由圆点分隔。通常情况下,包名称的元素被整个地小写。然而,类名称通常以一个大写字母开始,而且每个附加单词的首字母可以被大写以区分类名称中的单词。
5.10.2  import语句
Import语句
告诉编译器到哪儿寻找类来使用,必须先于所有类声明
        import abc.financeDept.*;
        public class Manager extends Employee {
          String department;
          Employee [] subordinates;
        }
    当需要使用包时,使用import语句来告诉编译器到哪儿去寻找类。事实上,包名称在包中(比如,abc.financedept)形成类的名称的一部分。你可以引用Employee类作为abc.financedept.Employee,或可以使用import语句及仅用类名称Employee。
import abc.financeDept.*;
        public class Manager extends Employee {
          String department;
          Employee [] subordinates;
        }
注—import语句必须先于所有类声明。                  
当使用一个包声明时,不必引入同样的包或该包的任何元素。记住,import语句被用来将其它包中的类带到当前名空间。当前包,不管是显式的还是隐含的,总是当前名空间的一部分。
5.10.3  目录布局及CLASSPATH环境变量
目录布局及CLASSPATH环境变量
    包被贮存在包含包名称的目录树中。
  package abc.financedept
  public class Employee  {
  }
  
  javac –d .  Employee.java
Employee.class的目录路径是什么?

   包被贮存在包含包名称分支的目录树中。例如,来自前面页中的Employee.class文件必须存在于下述目录中:
      path\abc\financeDept
    查寻类文件的包的目录树的根目录是在 CLASSPATH中。
    编译器的-d选项规定了包层次的根,类文件被放在它里面(前面所示的path)。
    Java技术编译器创建包目录,并在使用-d选项时将编译的类文件移到它当中。
c:\jdk1.2\source\> javac -d . Employee.java
将创建目录结构abc\financedept 在当前目录中(“.”)。
    CLASSPATH变量以前没有使用过,因为如果它没被设定,那么,工具的缺省行为将自动地包括类分布的标准位置和当前工作目录。如果想访问位于其它地方的包,那么必须设定CLASSPATH变量来显式地覆盖缺省行为。
c:\jdk1.2\source\>javac -d c:\mypackages Employee.java
    为了让编译器在编译前页中的Manager.java 文件时给abc.financedept. Employee类定位, CLASSPATH环境变量必须包括下述包路径:
      CLASSPATH=c:\mypackages;.

作者: starlight    时间: 2004-12-3 16:51     标题: SUN JAVA标准教程

练习:使用对象及类
    练习目的—会写、编译及运行三个程序,通过模仿使用银行帐目使用继承、构造函数及数据隐藏等面向对象概念。
一、准备
  为了成功地完成该实验,必须理解类和对象的概念。
二、任务
    一级实验:银行帐目
1.创建一个类,Account.java,它定义银行帐目。决定应该做什么样的帐目,需要贮存什么样的数据,以及将用什么样的方法。
2.使用一个包,bank,来包含类
    二级实验:帐目类型
1.修改一级实验,因而会针对CheckingAccount类的细节对Account划分子类。
2.允许检查帐目来提供溢出保护。
    三级实验:在线帐目服务
1.创建一个简单的应用程序,Teller.java,它使用一级或二级实验来提供一个在线帐目开户服务。
三、练习总结
    讨论—花几分钟时间来讨论一下实验练习中的经验、问题或发现。
-经验 解释 总结 应用
四、检查进步情况
    在继续下一个模块前,检查一下,确信你能:
-定义封装、多态性和继承
-使用访问修饰符private和public
-开发一个程序段来创建并初始化一个对象
-在一个特定的对象上调用方法
-描述构造函数和方法重载
-描述this引用起什么作用
-讨论为什么Java应用程序代码是可重用的                                    
    在Java软件程序中,确认:
-package语句
-import语句
-类成员函数和变量
-构造函数
-重载方法
-覆盖方法
-父类构造函数
五、思考
    既然理解了对象和类,如何在当前或今后工作中使用这个信息?

作者: starlight    时间: 2004-12-3 17:11     标题: SUN JAVA标准教程

第六章 高级语言特征
本模块讨论Java编程语言更多的面向对象特征。
第一节  相关问题
    讨论-下述问题与本模块中出现的材料相关:
-如何保持一个类或方法不被分成子类或被覆盖?
-如何将数组概念的使用扩展到对象?
第二节  目 的
    完成本模块的学习后,应该能
-描述static变量,方法和初始程序
-描述final类,方法和变量
-列出访问控制级别
-确认降级类并解释如何从JDK1.0升迁到JDK1.1到JDK1.2
-描述如何应用收集和反射
-在Java软件程序中,确认
-static方法和变量
-public,private,protected和缺省变量
-使用abstract类和方法
-解释如何以及何时使用内部类
-解释如何以及何时使用接口
-描述==和equals()之间的不同
第三节  类(static)变量
类(static)变量
    在所有类的实例中共享
    可以被标记为public或private
    如果被标记为public而没有该类的实例,可以从该类的外部访问
           public class Count {
             private int serialNumber;
             private static int counter = 0;
             public Count() {
               counter++;
               serialNumber = counter;
             }
           }
    有时想有一个可以在类的所有实例中共享的变量。比如,这可以用作实例之间交流的基础或追踪已经创建的实例的数量。
    可以用关键字static来标记变量的办法获得这个效果。这样的变量有时被叫做class variable,以便与不共享的成员或实例变量区分开来。
   public class Count {
             private int serialNumber;
             private static int counter = 0;
             public Count() {
               counter++;
               serialNumber = counter;
             }
           }
    在这个例子中,被创建的每个对象被赋于一个独特的序号,从1开始并继续往上。变量counter在所有实例中共享,所以,当一个对象的构造函数增加counter时,被创建的下一个对象接受增加过的值。  
    Static变量在某种程度上与其它语言中的全局变量相似。Java编程语言没有这样的全局语言,但static变量是可以从类的任何实例访问的单个变量。
    如果static变量没有被标记成private,它可能会被从该类的外部进行访问。要这样做,不需要类的实例,可以通过类名指向它。
public class StaticVar {
  public static int number;
}
public class OtherClass [
  public void method() {
    int x = StaticVar.number;
  }
}

作者: starlight    时间: 2004-12-3 17:11     标题: SUN JAVA标准教程

第四节类(static)方法
类(static)方法
    没有它所属的类的任何实例,static方法可以被调用
        public class GeneralFunction {
             public static int addUp(int x, int y) {
               return x + y;
             }
           }
           public class UseGeneral {
             public void method() {
               int a = 9;
               int b = 10;
               int c = GeneralFunction.addUp(a, b);
               System.out.println("addUp() gives " + c);
             }
           }
    当没有一个特殊对象变量的实例的时候,有时需要访问程序代码。用关键字static标记的方法可以这样使用,有时被称做class method。static方法可以用类名而不是引用来访问,如:
public class GeneralFunction {
             public static int addUp(int x, int y) {
               return x + y;
             }
           }
           public class UseGeneral {
             public void method() {
               int a = 9;
               int b = 10;
               int c = GeneralFunction.addUp(a, b);
               System.out.println("addUp() gives " + c);
             }
           }
    因为static方法不需它所属的类的任何实例就会被调用,因此没有this值。结果是,static方法不能访问与它本身的参数以及static变量分离的任何变量。访问非静态变量的尝试会引起编译错误。
注-非静态变量只限于实例,并只能通过实例引用被访问。
public class Wrong {
  int x;
  public static void main(String args[]) {
    x = 9; // COMPILER ERROR!
  }
}
Import points to remember about static methods:
    Main()是静态的,因为它必须在任何实例化发生前被顺序地访问,以便应用程序的运行。
    静态方法不能被覆盖成非静态。
第五节静态初始化程序
静态初始化程序
    在static block中,类可以包含方法程序中不存在的代码。
当类被装载时,静态代码块只执行一次。
    方法程序体中不存在的代码在static block中类可以包含该代码,这是完全有效的。当类被装载时,静态块代码只执行一次。类中不同的静态块按它们在类中出现的顺序被执行。
public class StaticInitDemo {
static int i = 5;
  static {
    System.out.println("Static code i= "+ i++ );
  }
}
public class Test {
  public static void main(String args[]) {
    System.out.println("Main code: i="
      + StaticInitDemo.i);
  }
}
将打印出:
Static code: i=5
Main code: i=6
Static 方法和数据

作者: starlight    时间: 2004-12-3 17:14     标题: SUN JAVA标准教程

){
23.  MyClass instance1 = new MyClass(1,2.0);
24.  MyClass instance2 = new MyClass(3,4.0);
25.  
26.  MyClass.statMethod(); //Outputs:statInt=4;
27.         //statDouble=16.0
28.
29.  instance1.instMethod(); //Outputs:instInt=1;
30.        //instDouble=2.0
31.  instance1.statMethod(); //Outputs:statInt=4;
32.        //statDouble=16.0
33.  
34.  instance2.instMethod(); //Outputs:instInt=3;
35.        //instDouble=4.0
36.  instance2.statMethod(); //Outputs:statInt=4;
37.        //statDouble=16.0
38.}
39.}
37.
    图6-1是MyClass类定义的框图。这个例子阐述了:
1.Static方法和数据的单个(共享)副本是因为类和该类的所有实例而存在。通过一个实例或通过类本身可以访问static成员。
2.非静态数据只限于实例,只能通过该实例的非静态方法对它进行访问。非静态数据定义对象之间互不相同的特点,非静态方法在它们所作用的非静态数据的基础上对每个对象的行为互不相同。
    考虑一下模仿汽车的特殊类型的一个对象的实例。轮子的大小,对该类型的所有汽车来说是个常量,可能被模仿成一个静态变量。颜色根据对象的不同而不同,其行为也根据对象的不同而不同,在它所作用的非静态数据的基础上对不同对象返回不同的颜色。

作者: starlight    时间: 2004-12-3 17:15     标题: SUN JAVA标准教程

第七节  关键字final
6.7.1  Final类
关键字final
    Final类不能被分成子类
Final方法不能被覆盖
Final变量是常数
  Java编程语言允许关键字Final被应用到类中。如果这样做了,类便不能被子分成子类。比如,类Java.lang.String就是一个final类。这样做是出于安全原因,因为它保证,如果方法有字符串的引用,它肯定就是类String的字符串,而不是某个其它类的字符串,这个类是String的被修改过的子类,因为String可能被恶意窜改过。
6.7.2  Final方法
    个体方法也可以被标记为final。被标记为final的方法不能被覆盖。这是由于安全原因。如果方法具有不能被改变的实现,而且对于对象的一致状态是关键的,那么就要使方法成为final。
    被声明为final的方法有时被用于优化。编译器能产生直接对方法调用的代码,而不是通常的涉及运行时查找的虚拟方法调用。
    被标记为static或private的方法被自动地final,因为动态联编在上述两种情况下都不能应用。
6.7.3  Final变量
    如果变量被标记为final,其结果是使它成为常数。想改变final变量的值会导致一个编译错误。下面是一个正确定义final变量的例子:
public final int MAX_ARRAY_SIZE = 25;
注-如果将引用类型(即,任何类的类型)的变量标记为final,那么该变量不能指向任何其它对象。但可能改变对象的内容,因为只有引用本身是final。
第八节抽象类
抽象类
    声明方法的存在而不去实现它的类被叫做抽象类
    可以通过关键字abstract进行标记将类声明为抽象
           public abstract class Drawing {
           public abstract void drawDot(int x, int y);
           public void drawLine(int x1, int y1,
                               int x2, int y2) {
             // draw using the drawDot() method repeatedly.
           }
         }
一个abstract类可以包含非抽象方法和变量
    有时在库开发中,要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该行为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。
    例如,考虑一个Drawing类。该类包含用于各种绘图设备的方法,但这些必须以独立平台的方法实现。它不可能去访问机器的录像硬件而且还必须是独立于平台的。其意图是绘图类定义哪种方法应该存在,但实际上,由特殊的从属于平台子类去实现这个行为。
    正如Drawing类这样的类,它声明方法的存在而不是实现,以及带有对已知行为的方法的实现,这样的类通常被称做抽象类。通过用关键字abstract进行标记声明一个抽象类。被声明但没有实现的方法(即,这些没有程序体或{}),也必须标记为抽象。
           public abstract class Drawing {
           public abstract void drawDot(int x, int y);
           public void drawLine(int x1, int y1,
                               int x2, int y2) {
             // draw using the drawDot() method repeatedly.
           }
         }
    不能创建abstract类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。
    Abstract类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类。
public class MachineDrawing extends Drawing {
  public void drawDot (int mach x, intmach y) {
           // Draw the dot
  }
}
Drawing d = new MachineDrawing();
第九节  接 口
接  口
    接口是抽象类的变体。
    在接口中,所有方法都是抽象的。
    多继承性可通过实现这样的接口而获得。
    句法是:
           public interface Transparency {
             public static final int OPAQUE=1;
             public static final int BITMASK=2;
             public static final int TRANSLUCENT=3;
             public int getTransparency();
           }
  接口是抽象类的变体。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。
    接口的好处是,它给出了屈从于Java技术单继承规则的假象。当类定义只能扩展出单个类时,它能实现所需的多个接口。
    接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即,将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof运算符可以用来决定某对象的类是否实现了接口。
    接口是用关键字interface来定义的,如下所述:
           public interface Transparency {
             public static final int OPAQUE=1;
             public static final int BITMASK=2;
             public static final int TRANSLUCENT=3;
             public int getTransparency();
           }
    类能实现许多接口。由类实现的接口出现在类声明的末尾以逗号分隔的列表中,如下所示:
     public class MyApplet extends Applet implements
       Runnable, MouseListener{
         "..."
       }
   下例表示一个简单的接口和实现它的一个类:
    interface SayHello {
        void printMessage();
    }
    class SayHelloImpl implements SayHello {
        void printMessage() {
            System.out.println("Hello");
        }
    }
    interface SayHello强制规定,实现它的所有的类必须有一个称做printMessage的方法,该方法带有一个void返回类型且没有输入参数。
接  口
    对于下述情况,界面是有用的:
    声明方法,期望一个或更多的类来实现该方法
    决定一个对象的编程界面,而不揭示类的实际程序体
    捕获无关类之间的相似性,而不强迫类关系
    描述“似函数”对象,它可以作为参数被传递到在其它对象上调用的方法中
    对于下述情况,接口是有用的:
    声明方法,期望一个或更多的类来实现该方法。
    揭示一个对象的编程接口,而不揭示类的实际程序体。(当将类的一个包输送到其它开发程序中时它是非常有用的。)
    捕获无关类之间的相似性,而不强迫类关系。
    描述“似函数”对象,它可以作为参数被传递到在其它对象上调用的方法中。它们是“函数指针”(用在C和C++中)用法的一个安全的替代用法。

作者: starlight    时间: 2004-12-3 17:16     标题: SUN JAVA标准教程

第十节  高级访问控制
高级访问控制
  修饰符      同类       同包      子类      通用性
  公共        是         是        是          是
  受保护      是         是        是
  缺省        是         是
  私有        是                                   
    变量和方法可以处于四个访问级别的一个中;公共,受保护,缺省或私有。类可以在公共或缺省级别。
    变量、方法或类有缺省访问性,如果它没有显式受保护修饰符作为它的声明的一部分的话。这种访问性意味着,访问可以来自任何方法,当然这些方法只能在作为目标的同一个包中的成员类当中。
    以修饰符protected标记的变量或方法实际上比以缺省访问控制标记的更易访问。一个protected方法或变量可以从类当中的任何方法进行访问,这个类可以是同一个包中的成员,也可以是从任何子类中的任何方法进行访问。当它适合于一个类的子类但不是不相关的类时,就可以使用这种受保护访问来访问成员。
            表6-1总结访问性标准
表6-1  访问性标准
                                                     
修饰符      同类       同包      子类      通用性
  公共        是         是        是          是
  受保护      是         是        是
  缺省        是         是
  私有        是                                    
受保护访问甚至被提供给子类,该子类驻留在与拥有受保护特征的类的不同包中。
第十一节降级
降    级
    降级就是过时的构造函数和方法调用。
    过时的方法和构造函数由具有更标准化的命名规则的方法所取代。
    当升迁代码时,用-deprecation标志来编译代码:
        javac -deprecation MyFile.java
    在JDK1.1中,对方法名称的标准化做了重大努力。因此,在JDK1.2中,大量的类构造函数和方法调用过时。它们由根据更标准化的命名规则规定的方法名称所取代,总的说来,使程序员的生活简单化。
    例如,在JDK1.1版本中的Java.awt.Component类:
  改变或获得组件大小的方法是resize()和size()。
  改变或获得组件矩形框的方法是reshape()和bounds()。
    在JDK1.0版本中的Java.awt.Component,这些方法被降级并被以set和get开头表示该方法的初级运算的方法所代替。
  setSize()和getSize()
  setBounds()getBounds()
    无论什么时候将代码从JDK1.0升迁到JDK1.1或更高版本中,或者即使使用以前用在JDK1.0中的代码,对用-deprecation标志来编译代码都是一个好主意。
c:\ javac -deprecation MyFile.java
    -deprecation标志将报告在降级过的类中使用的任何方法。例如,看一个叫做DateConverter的实用类,它将mm/dd/yy格式的日期转换成星期几:
1.package myutilities;
2.import java.util.*;
3.import java.text.*;
4.public final class DateConverter {
5.
6.  private static String day_of_the_week [] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
7.
8.public static String getDayOfWeek (String theDate){
9.  int month, day, year;
10.
11.  StringTokenizer st =
12.    new StringTokenizer (theDate, "/");
13.  month = Integer.parseInt(st.nextToken ());
14.  day = Integer.parseInt(st.nextToken());
15.  year = Integer.parseInt(st.nextToken());
16.  Date d = new Date (year, month, day);
17.  
18.  return (day_of_the_week[d.getDay()]);
19.  }
20.}
    当这个代码用-deprecation标志在JDK1.2中被编译时,会得到:
c:\ javac -deprecation DateConverter.java
DateConverter.java:16: Note: The constructor java.util.Date(int,int,int) has been deprecated.
            Date d = new Date (year, month, day);
                   ^
DateConverter.java:18: Note: The method int getDay() in class
java.util.Date has been deprecated.
                  return (day_of_the_week[d.getDay()]);
                                              ^
Note: DateConverter.java uses a deprecated API.Please consult the documentation for a better alternative. 3 warnings
    重写的DateConverter类看起来象这样:
1.package myutilities;
2.import java.util.*;
3.import java.text.*;
4.public final class DateConverter {
5.
6.private static String day_Of_The_Week [] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
      7.  
8.  public static String getDayOfWeek (String theDate){
9.    Date d = null;
10. SimpleDateFormat sdf =
11.   new SimpleDateFormat ("MM/dd/yy");
12. try {
13.   d = sdf.parse (theDate);
14. } catch (ParseException e) {
15.   System.out.println (e);
16.   e.printStackTrace();
17. }
18. // Create a GregorianCalendar object
19.Calendar c =
20. new GregorianCalendar (TimeZone.getTimeZone ("EST"),         Locale.US);
21.c.setTime (d);
22.return(day_Of_The_Week
               [(c.get(Calendar.DAY_OF_WEEK)-1)]);
23.  }
24.}
     
在这里,1.2版本使用两个新类:SimpleDateFormat,用来采用任何String日期格式并创建一个Date对象的类;以及GregorianCalendar类,用来创建一个带有当地时区和场所的日历。

作者: starlight    时间: 2004-12-3 17:16     标题: SUN JAVA标准教程

第十二节==运算符与equals()方法
==运算符与equals()方法
    equals()和==方法决定引用值是否指向同一对象
    equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
    Java.lang包中的Object类有public boolean equals (Object obj)方法。它比较两个对象是否相等。仅当被比较的两个引用指向同一对象时,对象的equals()方法返回true。
    ==运算符也进行等值比较。也就是说,对于任何引用值X和Y,当且仅当X和Y指向同一对象时, X==Y返回真。
    当两个分离的对象的内容和类型相配的话,String,Date,File类和所有其它override equals()的包装类(Integer,Double,等等)将返回真。
    例如,String类中的equals()方法返回true,当且仅当参数不为null并且是一个String对象,该对象与调用该方法的String对象具有相同的字符顺序。
String s1=new String(“JDK1.2”);
String s2=new String(“JDK1.2”);
方法s1.equals(s2)返回真,尽管s1和s2指向两个不同的对象。
第十三节toString()方法
toString()方法
    被用来将一个对象转换成String
    被用来将一个基本类型转换成String
    toString方法被用来将一个对象转换成String表达式。当自动字符串转换发生时,它被用作编译程序的参照。System.out.println()调用下述代码:
      Date now = new Date()
        System.out.println(now)
    将被翻译成:
          System.out.println(now.toString());
    对象类定义缺省的toString()方法,它返回类名称和它的引用的地址(通常情况下不是很有用)。许多类覆盖toString()以提供更有用的信息。例如,所有的包装类覆盖toString()以提供它们所代表的值的字符串格式。甚至没有字符串格式的类为了调试目的常常实现toString()来返回对象状态信息。
第十四节  内部类
内部类
    被附加到JDK1.1
    允许一个类定义被放到另一个类定义里
    把类在逻辑上组织在一起
    可访问它们所嵌套的类的范围
    内部类,有时叫做嵌套类,被附加到JDK1.1及更高版本中。内部类允许一个类定义被放到另一个类定义里。内部类是一个有用的特征,因为它们允许将逻辑上同属性的类组合到一起,并在另一个类中控制一个类的可视性。
6.14.1  内部类基础
    下述例子表示使用内部类的共同方法:
1.import java.awt.*;
2.import java.awt.event.*;
3.public class MyFrame extends Frame{
4.    Button myButton;
5.    TextArea myTextArea;
6.    int count;;
7.
8.    public MyFrame(){
9.        super("Inner Class Frame");
10.     myButton = new Button("click me");
11.     myTextArea = new TextArea();
12.     add(myButton,BorderLayout,CENTER);
13.     add(myTextArea,BorderLayout,NORTH);
14.     ButtonListener bList = new ButtonListener();
15.     myButton.addActionListener(bList);
16. }
17. class ButtonListener implements ActionListener{
18.   public void actionPerformed(ActionEvent e){
19.   count ++
20.     myTextArea.setText("button clicked" + {
21.         count + "times");
22.   }
23. }// end of innerclass ButtonListener
24.
25. public static void main(String args[]){
26.   MyFrame f = new MyFrame();
27.   f.setSize(300,300);
28.   f.setVisible(true);
29. }
30.} // end of class MyFrame
    前面的例子包含一个类MyFrame,它包括一个内部类ButtonListener。编译器生成一个类文件,MyFrame$ButtonListener.class以及toMyFrame.class。它包含在MyFrame.class中,是在类的外部创建的。
6.14.2  如何做内部类工作?
    内部类可访问它们所嵌套的类的范围。所嵌套的类的成员的访问性是关键而且很有用。对嵌套类的范围的访问是可能的,因为内部类实际上有一个隐含的引用指向外部类上下文(如外部类“this”)。
1.public class MyFrame extends Frame{
2.    Button myButton;
3.    TextArea myTextarea;
4.    public MyFrame(){
5.      ......................
6.      ......................
7.      MyFrame$ButtonListener bList = new
8.               MyFrame$ButtonListener(this);
9.      myButton.addActionListener(bList);
10.   }
11.   class MyFrame$ButtonListener implements
12.   ActionListener{
13.   private MyFrame outerThis;
14.   Myframe$ButtonListener(MyFrame outerThisArg){
15.      outerThis = outerThisArg;
16.   }
17.   
18.   public void actionPerformed(ActionEvent e) {
19.   outerThis.MyTextArea.setText("buttonclicked");
20.   ......................
21.   ......................
22.   }
23.   public static void main(String args[]){
24.     MyFrame f = new MyFrame();
25.     f.setSize(300,300);
26.     f.setVisible(true);
27.   }
28.}
    有时可能要从static方法或在没有this的某些其它情况下,创建一个内部类的一个实例(例如,main)。可以如下这么做:
public static void main(String args[]){
    MyFrame f = new MyFrame();
    MyFrame.ButtonListener bList =
           f.new ButtonListener();
    f.setSize(50,50);
    f.setVisible(true);
}
6.14.3  内部类属性
内部类属性
    类名称只能用在定义过的范围中,除非用限定的名称。
    内部类的名称必须与所嵌套的类不同。
    内部类可以被定义在方法中。
    任何变量,不论是本地变量还是正式参数,如果变量被标记为final,那么,就可以被内部类中的方法访问。
    内部类有如下属性:
    类名称只能用在定义过的范围中,除非用在限定的名称中。内部类的名称必须与所嵌套的类不同。
    内部类可以被定义在方法中。这条规则较简单,它支配到所嵌套类方法的变量的访问。任何变量,不论是本地变量还是正式参数,如果变量被标记为final,那么,就可以被内部类中的方法访问。
内部类可以使用所嵌套类的类和实例变量以及所嵌套的块中的本地变量。
内部类可以被定义为abstract.
    属性
    只有内部类可以被声明为private或protected,以便防护它们不受来自外部类的访问。访问保护不阻止内部类使用其它类的任何成员,只要一个类嵌套另一个。
    一个内部类可以作为一个接口,由另一个内部类实现。
    被自动地声明为static的内部类成为顶层类。这些内部类失去了在本地范围和其它内部类中使用数据或变量的能力。
    内部类不能声明任何static成员;只有顶层类可以声明static成员。因此,一个需求static成员的内部类必须使用来自顶层类的成员。
注-内部类有常常被用作创建事件适配器的方便特征。事件适配器将在后面模块中讨论。
第十五节  包装类
包装类
用来将基本数据元素看作对象,包装类可以被用作:
                                    
            基本数据类型     包装类
              boolean             Boolean
                   byte                Byte
                   char                Char
                   short               Short
                   int                 Int
                   long                Long
                   float               Float
                   double              Double
    Java编程语言不把基本数据类型看作对象。例如,在基本格式本身当中,数字、布尔及字符型数据都被看作是为了提高效率。Java编程语言提供包装类来将基本数据元素看作对象。这样的数据元素被包裹在创建于它们周围的对象中,每个Java基本数据类型在Java.lang包中都有一个相应的wrapper class。每个包装类对象封装一个基本值。
              包装类列表如下:
              表6-2  包装类
                                    
            基本数据类型     包装类
              boolean        Boolean
              byte           Byte
              char           Char
              short          Short
              int            Int
              long           Long
              float          Float
              double         Double
    可以通过将被包裹的值传递到合适的构造函数中来构造包装类对象。例如:
int pInt = 500;
Integer wInt = new Integer(pInt);
第十六节  收集API
收集API
    收集(或容器)是代表一个对象组的单个对象,被认为是它的元素。
    收集类Vector,Bits,Stack,Hashtable,LinkedList等等都被支持。
    收集API包括将对象保持为下述情况的界面:
      收集-没有具体顺序的一组对象
      设定-没有复制的一组对象
      列表-有序对象组,允许复制
    收集(或容器)是代表一个对象组的单个对象,被认为是它的元素。收集典型地处理许多对象的类型,所有的类型都有一个特殊的种类(也就是说,它们都是从一个共同父类型延续来的)。Java编程语言支持收集类Vector,Bits, Stack,Hashtable ,LinkedList等等。例如,Stack实现后进先出(LIFO)的顺序,Hashtable提供一个相关的对象数组。
    收集保持处理Object类型的对象。这允许在收集中贮存任何对象。它还可以,在使用对象前、从收集中检索到它之后,使用正确的类型转换。
    收集API典型地由将对象保持为下述情况的接口而组成:
      收集-没有具体顺序的一组对象
      设定-没有复制的一组对象
      列表-有序对象组,允许复制
    API还包括诸如HashSet, ArraySet, ArrayList, LinkedList和Vector等等的类,它们实现这些接口。API还提供了支持某些算法的方法,如:排序,二进制搜索,评估列表中的最小和最大,以及收集等。

作者: starlight    时间: 2004-12-3 17:19     标题: SUN JAVA标准教程

= { 'a', 'b', 'c', 'd'};
44.  String s = new String ("Hi there!");
45.
46.  v.addInt(digit);
47.  v.addFloat(real);
48.  v.addString(s);
49.  v.addCharArray(letters);
50.
51.  v.printVector();
52. }
53.}
    这个程序产生下列输出:
$ java MyVector
Number of vector elements is 4 and are:
5
3.14
Hi there!
Abcd

作者: starlight    时间: 2004-12-3 17:19     标题: SUN JAVA标准教程

第十八节  反射API
反射API
    可以用作
      构造新类实例和新数组
      访问并修改对象和类的字段
      调用对象和类中的方法
      访问并修改数组的元素
    Java反射API提供一套类,可以用它们来决定一个类文件的变量和方法。因为被共同用于动态发现和执行代码的目的,因此API可以被用于:
  构造新类实例和新数组
  访问并修改对象和类的字段
  调用对象和类中的方法
  访问并修改数组的元素
    只要安全策略允许,这些操作是可能的。在需要运行时检索并处理信息的情况下,反射API是有用的。例如,如果正在编写一个Java软件解释程序或调试程序,可以使用它。
第十九节  反射API特征
反射API特征
Java.lang.Class
    Java.lang.reflect.Field
    Java.lang.reflect.Method
    Java.lang.reflect.Array
Java.lang.reflect.Constructor
    定义类和方法的核心反射API的主要特征如下:
      Java.lang.Class类提供方法,该方法可获得有关类及其字段、构造函数以及方法的信息。
      Java.lang.reflect.Field提供方法,该方法设定/获得有关类中的字段的信息。
      Java.lang.reflect.Method提供方法,该方法访问并调用类中的方法,并获得它们的签名。
      Java.lang.reflect.Array能使数组对象自省。
      Java.lang.reflect.Constructor提供反射访问到构造函数。
第二十节  反射API安全模型
反射API安全模型
Java安全管理器一个类接一个类地控制对核心API的访问。
    当下述情况发生时,标准的Java编程语言访问控制得到加强:
  Field被用来获得或设定一个字段值
  Method被用来调用一个方法
      Constructor被用来创建并初始化一个新的类的实例
    Java安全管理器一个类接一个类地控制对核心API的访问。当下述情况发生时,标准的Java编程语言访问控制得到加强:
  Field被用来获得或设定一个字段值
  Method被用来调用一个方法
      Constructor被用来创建并初始化一个新的类的实例
练习:用高级语言特征工作
    练习目的—使用银行帐户模型和采用高级面向对象特征,如:内部类,矢量类和接口等,重写、编译并运行三个程序。
一、准备
    为了成功地完成该实验,必须熟悉本模块及前面模块中所讲的面向对象概念。
二、任务
    一级实验:修改银行帐户问题
1.定义只包含两个方法deposit和withdraw的接口Personal。
2.从模块5中,运用Personal接口来定义一套不同的帐户类型,重新定义类Account.Java。它必须能处理个人帐户,进一步分成支票和存款两个帐户。
3.设计并开发提供保护的方法。例如,如果一个客户有一个存款和支票帐户,须确保支票帐户受存款帐户保护。
    二级实验:使用内部类
1.创建一个叫做BasicArray的类,声明并初始化一个叫做thisArray的数组,它包含四个整数。
2.创建一个名为Factorial的类,它包含一个计算它的参数的阶乘的方法。
3.从BasicArray的主要方法创建Factorial类的一个实例,然后调用其方法来计算四个整数中每一个的阶乘。
4.编译并测试该程序。
5.将Factorial类中的所有东西都移到BasicArray类中。Factorial现在就是BasicArray的一个内部类。
6.编译并测试该程序。
    三级实验:将find和delete方法附加到MyVector类中
1.将Find方法附加到MyVector类中,它将返回被作为参数传递的元素的位置。
如果未发现该参数,让方法返回-1。
例如:
$ java MyVectorFind 3.14
3.14 is located at index 1
Number of vector elements is 4 and are:
5
3.14
Hi there!
abcd
$ java MyVectorFind c
args[0]=c, not found in vector
Number of vector elements is 4 and are:
5
3.14
Hi there!
abcd
2.将delete方法附加到MyVector类中,该类将所有与参数相配的元素移走。
方法必须返回true或false:如果删除成功,为true;否则为false(元素存在或不存在于矢量中)。
例如:
$ java MyVectorDelete 3.14
Elements 3.14 successfully deleted from vector.
Number of vector elements is 3 and are:
5
Hi there!
abcd
三、练习总结
    讨论—花几分钟来讨论实验练习中遇到的经验、问题或发现。
经验  解释   总结  应用
四、检查进步情况
    在继续学习下个模块前,检查一下你确实能:
  描述static变量、方法和初始化程序
  描述final类、方法和变量
  列出访问控制级别
  确认降级类并解释如何从JDK1.0升迁到JDK1.1、JDK1.2。
  在Java软件程序中,确认:
    static方法和变量
    public,private,protected和缺省变量
  使用abstract类和方法
  解释如何及何时使用内部类
  解释如何及何时使用接口
  描述= =和equals()之间的不同
五、思考
    Java编程语言具有什么特征,从而可以直接处理运行时错误情况?

作者: starlight    时间: 2004-12-8 15:37     标题: SUN JAVA标准教程

);
11.    } catch (ArrayIndexOutOfBoundsException e){
12.    System.out.println( "Re-setting Index Value");
13.    i = -1;
14.    } finally {
15.    System.out.println("This is always printed");
16.    }
17.    i++;
18.    } // end while()
19.    } // end main()
    当循环被执行时,下述在屏幕上出现的信息将改变。
1.Hello world!
2.This is always printed
3.No, I mean it!
4.This is always printed
5.HELLO WORLD!!
6.This is always printed
7.Re-setting Index Value
8.This is always printed

作者: starlight    时间: 2004-12-8 15:40     标题: SUN JAVA标准教程

第五节  异常分类
    在Java编程语言中,异常有三种分类。Java.lang.Throwable类充当所有对象的父类,可以使用异常处理机制将这些对象抛出并捕获。在Throwable类中定义方法来检索与异常相关的错误信息,并打印显示异常发生的栈跟踪信息。它有Error和Exception两个基本子类,如下图所示:
    Throwable类不能使用,而使用子类异常中的一个来描述任何特殊异常。每个异常的目的描述如下:
-Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
-RuntimeException表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。比如,如果数组索引扩展不超出数组界限,那么,ArrayIndexOutOfBoundsException异常从不会抛出。比如,这也适用于取消引用一个空值对象变量。因为一个正确设计和实现的程序从不出现这种异常,通常对它不做处理。这会导致一个运行时信息,应确保能采取措施更正问题,而不是将它藏到谁也不注意的地方。
-其它异常表示一种运行时的困难,它通常由环境效果引起,可以进行处理。例子包括文件未找到或无效URL异常(用户打了一个错误的URL),如果用户误打了什么东西,两者都容易出现。这两者都可能因为用户错误而出现,这就鼓励程序员去处理它们。
第六节  共同异常
共同异常
-ArithmeticException
-NullPointerException
-NegativeArraySizeException
-ArrayIndexoutofBoundsException
-SecurityException
    Java编程语言提供几种预定义的异常。下面是可能遇到的更具共同性的异常中的几种:
-ArithmeticException—整数被0除,运算得出的结果。
-int I =12 / 0;
-NullPointerException—当对象没被实例化时,访问对象的属性或方法的尝试:
-Date d= null;
-System.out.println(d.toString());
-NegativeArraySizeException—创建带负维数大小的数组的尝试。
-ArrayIndexoutofBoundsException—访问超过数组大小范围的一个元素的尝试。
-SecurityException—典型地被抛出到浏览器中,SecurityManager类将抛出applets的一个异常,该异常企图做下述工作(除非明显地得到允许):
-访问一个本地文件
-打开主机的一个socket,这个主机与服务于applet的主机不是同一个。
-在运行时环境中执行另一个程序
第七节  处理或声明规则
处理或声明规则
-用try-catch-finally块来处理异常
-使用throws子句声明代码能引起一个异常
     为了写出健壮的代码,Java编程语言要求,当一个方法在栈(即,它已经被调用)上发生Exception(它与Error或RuntimeException不同)时,那么,该方法必须决定如果出现问题该采取什么措施。
    程序员可以做满足该要求的两件事:
    第一,通过将Try{}catch(){}块纳入其代码中,在这里捕获给被命名为属于某个超类的异常,并调用方法处理它。即使catch块是空的,这也算是处理情况。
    第二,让被调用的方法表示它将不处理异常,而且该异常将被抛回到它所遇到的调用方法中。它是按如下所示通过用throws子句标记的该调用方法的声明来实现的:
     public void troublesome() throws IOException
    关键字throws之后是所有异常的列表,方法可以抛回到它的调用程序中。尽管这里只显示了一个异常,如果有成倍的可能的异常可以通过该方法被抛出,那么,可以使用逗号分开的列表。
    是选择处理还是选择声明一个异常取决于是否给你自己或你的调用程序一个更合适的候选的办法来处理异常。
注—由于异常类象其它类一样被组编到层次中,而且由于无论何时想要使用超类都必须使用子类, 因此,可以捕获异常“组”并以相同的捕获代码来处理它们。例如,尽管IOExceptions(EOFException,FileNotFoundException等等)有几种不同的类型,通过俘获IOException,也可以捕获IOException任何子类的实例。
第八节  创建自己的异常
7.8.1  介绍
    用户定义异常是通过扩展Exception类来创建的。这种异常类可以包含一个“普通”类所包含的任何东西。下面就是一个用户定义异常类例子,它包含一个构造函数、几个变量以及方法:
1.public class ServerTimedOutException extends Exception {
2.    private String reason;
3.    private int port;
4.    public ServerTimedOutException (String reason,int port){
5.      this.reason = reason;
6.      this.port = port;
7.    }
8.    public String getReason() {
9.    return reason;
10.    }
11.    public int getPort() {
12.      return port;
13.    }
14. }
    使用语句来抛出已经创建的异常:
throw new ServerTimedOutException
("Could not connect", 80);
7.8.2  实例
    考虑一个客户服务器程序。在客户代码中,要与服务器连接,并希望服务器在5秒钟内响应。如果服务器没有响应,那么,代码就如下所述抛出一个异常(如一个用户定义的ServerTimedOutException)。
1.  public void connectMe(String serverName) throws
     ServerTimedOutException {
2.int success;
3.int portToConnect = 80;
4.success = open(serverName, portToConnect);
5.if (success == -1) {
6.throw new ServerTimedOutException(
7."Could not connect", 80);
8.}
9.}
    要捕获异常,使用try语句:
1.public void findServer() {
2.. . .
3.try {
4.connectMe(defaultServer);
5.} catch(ServerTimedOutException e) {
6.System.out.println("Server timed out, trying alternate");
7.try {
8.connectMe(alternateServer);
9.} catch (ServerTimedOutException e1) {
10.System.out.println("No server currently available");
11.}
12.}
13... .
注—try和catch块可以如前例所述那样被嵌套。
也可能部分地处理一个异常然后也将它抛出。如:
try {
.....
.....
} catch (ServerTimedOutException e) {
  System.out.println("Error caught ");
  throw e;
}
练习:处理并创建异常
    练习目的—通过编写可以创建并处理异常的Java软件程序,可以获得异常机制的经验。
一、准备
    为了成功地完成该实验,必须理解处理运行时错误的异常的概念。
二、任务
    一级实验:处理一个异常
    1. 使用第169页上的样板异常程序在数组索引超出数组大小时创建一个异常。(或修改自己的程序以便创建一个异常。)
    2. 使用try和catch语句从异常进行恢复。
    二级实验:创建自己的异常
使用模块5中创建的bank包并附加下述异常:
AccountOverdrawnException—当有了这个要取出比帐户上更多的钱的尝试时。
InvalidDepositException—当无效钱数(小于0)存入时。
三、练习总结
    讨论—花几分钟时间讨论实验练习中所取得的经验、问题或发现。
经验  解释 总结 应用
四、检查进步情况
    在继续下一个模块前,检查一下,确信能够:
-定义异常
-使用try,catch和finally语句
-描述异常分类
-确认共同异常
-开发程序来处理自己的异常
五、思考
Java应用环境有什么特征,使它支持用户界面的开发?

作者: starlight    时间: 2004-12-8 15:43     标题: SUN JAVA标准教程

第八章  建立GUIs
  本模块讲述图形用户界面的建立及布局。它介绍了抽象视窗工具包,一种建立GUIs的类包。
第一节  相关问题
  讨论—下述问题与本模块中出现的材料相关。
-Java编程语言是一个具有独立平台的编程语言。GUI环境通常是从属平台。那么,为了使GUI平台独立,Java技术是如何接近这个主题的呢?
第二节  目 的
    完成本模块学习时,将能:
-描述AWT包及其组件
-定义Container、Component及Layout Manager等术语,以及它们是如何在一起来建立GUI的
-使用Layout Manager
-使用Flow、Border、Gird及Card布局管理器来获得期望的动态布局
-增加组件到Container
-正确运用Frame及Panel容器
-描述如何使用嵌套容器来完成复杂的布局
-在Java软件程序中,确认如下内容:
-容器
-相关布局管理器
-所有组件的布局层次
第三节  AWT
AWT
-提供基本的GUI组件,用在所有的Java applets及应用程序中
-具有可以扩展的超类,它们的属性是继承的,类也可被抽象化
-确保显示在屏幕上的每个GUI组件都是抽象类组件的子类
-Contaner,它是一个Component的抽象子类,而且包括两个子类
-Panel
-window
    AWT提供用于所有Java applets及应用程序中的基本GUI组件,还为应用程序提供与机器的界面。这将保证一台计算机上出现的东西与另一台上的相一致。
    在学AWT之前,简单回顾一下对象层次。记住,超类是可以扩展的,它们的属性是可继承的。而且,类可以被抽象化,这就是说,它们是可被分成子类的模板,子类用于类的具体实现。
    显示在屏幕上的每个GUI组件都是抽象类组件的子类。也就是说,每个从组件类扩展来的图形对象都与允许它们运行的大量方法和实例变量共享。
    Container是Component的一个抽象子类,它允许其它的组件被嵌套在里面。这些组件也可以是允许其它组件被嵌套在里面的容器,于是就创建了一个完整的层次结构。在屏幕上布置GUI组件,容器是很有用的。Panel是Container的最简单的类。Container的另一个子类是Window。
第四节  Java.awt包
    Java.awt包包含生成WIDGETS和GUI组件的类。该包的基本情况如下图所示。黑体字的类表明该模块的要点。

作者: starlight    时间: 2004-12-8 15:44     标题: SUN JAVA标准教程

) {
6.MyFrame fr = new MyFrame("Hello Out There!");
7.fr.setSize(500,500);
4.fr.setBackground(Color.blue);
5.        fr.setVisible(true);
6.     }
7.    public MyFrame (String str) {
8.         super(str);
9.    }
10.}
    上述程序创建了下述框架,它有一个具体的标题、大小及背景颜色。

作者: starlight    时间: 2004-12-8 15:47     标题: SUN JAVA标准教程

) {
10.        FrameWithPanel fr =
11.        new FrameWithPanel ("Frame with Panel");
12.        Panel pan = new Panel();
13.        
14.        fr.setSize(200,200);
15.        fr.setBackground(Color.blue);
16.        fr.setLayout(null); //override default layout mgr
17.        pan.setSize (100,100);
18.        pan.setBackground(Color.yellow);
19.
20.        fr.add(pan);
21.        fr.setVisible(true);
22.     }
23.    ....
24.

作者: starlight    时间: 2004-12-8 15:49     标题: SUN JAVA标准教程

) {
9.        ExGui guiWindow = new ExGui();
10.        guiWindow.go();
11.      }
12.
13.      public void go() {
14.        f = new Frame("GUI example");
15.        f.setLayout(new FlowLayout());
16.        b1 = new Button("Press Me");
17.        b2 = new Button("Don't Press Me");
18.        f.add(b1);
19.        f.add(b2);
20.        f.pack();
21.        f.setVisible(true);
22.      }
23.}
    main()方法
    本例中第8行main()方法有两个作用。首先,它创建了ExGui对象的一个实例。回想一下,直到一个实例存在,还没有被称做f,b1和b2的真实数据项可以使用。第二,当数据空间被创建时,main()在该实例的上下文中调用实例方法go()。在go()中,真正的运行才开始。
    new Frame (“GUI Example”)
    这个方法创建Java.awt.Frame类的一个实例。根据本地协议,在Java编程语言中,Frame是顶级窗口,带有标题条—在这种情况下,标题条由构造程序参数“GUI Example”定义—缩放柄,以及其它修饰。
    f.setLayout (new FlowLayout())
    这个方法创建Flow布局管理器的一个实例,并将它安装在框架中。对于每个Frame、Border布局来说,都有一个布局管理器,但本例中没有使用。Flow布局管理器在AWT中是最简单的,它在某种程度上象一个页面中的单词被安排成一行一行的那样来定位组件。请注意,Flow布局缺省地将每一行居中。
    new Button(“Press Me”)
    这个方法创建Java.awt.Button类的一个实例。按钮是从本地窗口工具包中取出的一个标准按钮。按钮标签是由构造程序的字符串参数定义的。
    f.add(b1)
    这个方法告诉框架f(它是一个容器),它将包容组件b1。b1的大小和位置受从这一点向前的Frame布局管理器的控制。
    f.pack()
    这个方法告诉框架来设定大小,能恰好密封它所包含的组件。为了确定框架要用多大,f.pack()询问布局管理器,在框架中哪个负责所有组件的大小和位置。
    f.setVisible(true)
    这个方法使框架以及其所有的内容变成用户看得见的东西。
    第190页代码的最终结果是:

8.9.1  Flow布局管理器
    第190页例子中所用的Flow布局对组件逐行地定位。每完成一行,一个新行便又开始。
    与其它布局管理器不一样,Flow布局管理器不限制它所管理的组件的大小,而是允许它们有自己的最佳大小。
    如果想将组件设定缺省居中的话,Flow布局构造程序参数允许将组件左对齐或右对齐。
    如果想在组件之间创建一个更大的最小间隔,可以规定一个界限。
    当用户对由Flow布局管理的区域进行缩放时,布局就发生变化。如:

作者: 飞鸟设计    时间: 2005-2-21 09:25     标题: SUN JAVA标准教程

呵呵 有没有后续啦??老深~~
作者: 慕容豪情    时间: 2005-3-13 16:46     标题: SUN JAVA标准教程

晕~你给我发本书  出来了?





欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/) Powered by Discuz! 7.2