• 1. 第一章 Java语言概述1
  • 2. 1.1 Java的历史(前身)OAK(James Gosling 1990) 90年,Sun公司开始Green工程 93年,WWW席卷全球 94年,开始定位于Internet 95年,Java命名 Hotjava, 第一个支持Java的浏览器 Netscape2.0 1995.5.23 Java诞生(Java1.0.2 API) 1997.2.18 JDK1.1 (java1.1 API) VJ++6.0、cafe、JBuilder …. 支持 1998.12 JDK1.2 (Java 2 SDK v1.2 Standard Edition) …… 2009. JDK 1.6 2011. JDK 1.72
  • 3. http://java.sun.com http://www.oracle.com/technetwork/java/Java资源网址3
  • 4. Simple : 易学;自动内存管理;简化重载;去掉指针及C++中一些不是绝对必要的功能… object-oriented: 纯面向对象语言,程序代码以类的形式组织,由类来定义对象的各种状态和行为… Distributed : 丰富的网络编程功能-轻松处理TCP/IP ;通过URL访问远地资源;字节码可来自网络…1.2 Java语言特点4
  • 5. Interpreted: Java是解释型的,但Java通过预先将源代码编译为接近于机器指令的字节码,有效地克服了传统解释型语言的性能瓶颈,同时又保持了解释型语言的可移植性;Java解释器能直接在任何机器上执行Java字节码… Robust: 静、动态检查,排除出现错误的条件;异常处理机制,正确处理运行时的错误;取消指针,保护内存数据与程序;数据类型的匹配,数组下标越界检查;自动内存管理,碎片收集…5
  • 6. Secure: 用于网络/分布式运算环境,确保建立无病毒且不会被侵入的系统;内存分配及布局由Java运行系统决定;字节码加密传输,客户端校验… architecture-neutral: Java应用程序能够在网络上任何地方执行;字节代码 - 平台无关性;完全统一的语言版本 - 实现无关性;访问底层操作系统功能的扩展类库 – 不依赖于具体系统… Portable: 源于平台无关性,且Java本身环境的可移植性…6
  • 7. high-performance: 字节码-> 目标代码;JIT(Just-In-Time)即时时编译器… multi-threaded: 在语言级嵌入了对并发控制的功能 - 多线程控制,大大简化了多线程应用程序的开发 … Dynamic: 面向对象设计的延伸。JAVA的基本组成单元是类,而Java的类又是运行时动态装载的。可以在分布环境中动态地维护应用程序和类库的一致性。更能适应时刻变化的环境。Java不会因程序库的更新,而必须重新编译程序…7
  • 8. 1.3 Java开发环境与工具Java技术包括两部分: Java程序设计语言 Java平台。 Java 语言是一种广泛使用的高水平的程序设计语言,是一个有力的软件平台。这个语言平台为软件开发提供了一整套必备的工具和功能实现,具体如下列的功能: 开发工具:提供编译、运行、监视、调试和应用程序文档生成等开发工具。对于初学者,主要使用的工具有:编译工具javac,运行工具java, 文档生成工具javadoc。 8
  • 9. 应用程序接口API:API提供Java程序设计语言的核心功能。比如队列,网络,安全,XML,数据库访问。核心API包含的内容非常大,具体可查阅SDK文档。 部署技术:JDK提供了标准机制部署你的应用程序给最终用户,例如 Java Web Start 和 Java技术。 用户界面工具箱:Swing 和 Java 2D toolkits 用于创建传统的图形用户界面(GUIs)。 其他功能综合库:包含如IDL, JDBC, JNDI, RMI, RMI-IIOP 等。9
  • 10. Java程序开发和运行环境的组成:10
  • 11. Java程序设计语言是一种高级语言,它用我们熟悉的字词、句等表述需要计算机为我们做的事情。大多数程序设计语言,都要经过编译或解释以便能在计算机上运行。 在Java程序设计语言中,所有源代码写在一个扩展名是.java的纯文本文件里。这些源文件通过Java编译器(javac.exe)编译成.class文件。.class文件不包含本地处理器的代码,而包含Java虚拟机机器语言代码,它是一种在Java平台上被解释器解释的平台无关代码,称之为“字节码”。1.Java程序设计语言11
  • 12. Java执行工具(java)用来运行.class文件,它是一个解释程序,又称“Java虚拟机”,它负责解释分解并执行每个Java字节码指令。下图反映这个过程:12
  • 13. Java虚拟计算机,可以认为Java字节码像机器指令码一样。任何Java解释器,不论是开发工具的,还是运行applet的web浏览器,都可认为是运行的Java虚拟计算机。Java虚拟机在许多不同的操作系统都是有效的,所以同样的.class文件有能力运行在Windows、Solaris、 Linux、MacOS等多种操作系统下,如图: 13
  • 14. 2.Java平台 平台是程序运行的硬件和软件环境。我们已经了解的一些流行平台像Windows、Linux、Solaris和MacOS等。多数平台被描述成操作系统与硬件的复合体。Java平台不同于其它平台,它是一个纯软件平台,在其它硬件基础平台上运行,如下图:。本地计算机系统Java虚拟机(JVM).class 二进制字节码文件 .java java源程序文件14
  • 15. Java平台有两个部分: Java虚拟机(Java VM) Java应用程序接口(Java API) Java虚拟机是Java平台的基础,是在各种不同的硬件基础平台上的接入口。Java字节码程序就是由它解释并执行,同时提供程序的运行环境。 Java API是一个巨大的,提供许多有用功能的,软件组成的集合体。Java API被组合在库中,由相关的类和接口构成,这些库称做“包”。下图表示运行在Java平台上的程序。图中显示,Java API和虚拟机把程序与硬件隔离开,Java程序通过API在VM上运行。 15
  • 16. 16
  • 17. J2 SDK JRE JVMJVM plus all APIs, compilers ,tools, and documentation (what you need in order to write java technology programs). JVM plus basic APIs (what you need to distribute to people who will run your Java programs) 17
  • 18. 3 Java术语JVM - java虚拟机 JVM将 java 字节码程序翻译成机器语言。然后由计算机执行。 JRE - java 运行环境 JRE 是由JVM 和 java platform 核心类以及相关支撑文件组成。 API - Application programming interface. API 是rules(syntax) :在java技术中如何编程。 API包括数百个类——公司预先编好的代码,你可以在编程中充分利用它们的功能。18
  • 19. JDK — java developer’s kit (java开发工具包) JDK 包含JVM和其他工具,以及所有的API和相关的文件。 JDK 是java 技术的旧名(1999年11月以前采用), JDK1.1 是最后版本。 Java 2 — Java 2 Platform, J2 SDK –java技术的新名称。 SDK — Software Development Kit19
  • 20. 4.Java虚拟机JVM提供以下定义: 指令集(Bytecodes 是JVM的机器指令)。 寄存器组 类文件格式 栈 垃圾回收“堆”(实现内存的动态分配和自动回收) 内存区域 Java程序执行时,首先虚拟机对要执行的class文件装载,然后对字节码进行验证,最后用解释器对字节码解释执行,下图是jvm的逻辑构造。20
  • 21. 类装配器字节码验证器解释器本地计算机系统代码生成器 JIT code generatorXxx.class21
  • 22. 加载代码 — 类装配器 加载程序运行所需要的所有的类。类装配器将本地文件系统的类的名字空间与从网络资源来的类的名字空间分开。这样就限制了特洛伊木马程序,因为本地类总是首先加载。 一旦所有的类被加载,可执行程序的内存布局就被确定了。内存地址被分配给符号引用表,查找表被建立。由于内存的布局出现在运行时刻,防止了对于代码域的未授权的访问。22
  • 23. 验证代码 — 字节码验证器 java代码在你的机器上执行前要经过几个测试。字节码验证器测试代码段的格式,检查代码段是否有非法代码(伪造指针,对象上的非法存取,试图改变对象类型等)。 所有网络来的类文件都要经过字节码验证。 执行代码 — 解释器23
  • 24. 5.Java开发工具Java开发工具是用于编写编写和生成Java程序。对于现有的计算机平台,必须安装Java开发工具箱,即Java Development Kit,简称“JDK”,才能够运行和开发Java程序 。JDK由Sun公司提供,其安装包可以从Sun公司的Java网站下载获得,网站地址: http://java.sun.com 。 注意,Sun公司针对不同的平台提供了各自不同的安装包,下载时根据需要选择下载。 JDK仅为程序开发者提供了一个基本的Java程序编写环境,对于那些大型的复杂的Java程序,需要一种综合集成的大型开发工具。24
  • 25. 1.4 建立Java平台和开发环境1.建立Java平台 Java平台的建立只需安装JDK或JRE就可以完成。JRE是Java运行环境(Java Runtime Environment)缩写,如果仅仅用来运行Java程序,仅安装JRE就可以了。如果需要开发和运行Java程序,就必须安装JDK。 第一步:下载JDK。 通常到sun的Java网站去下载JDK的安装包程序,当然也可以从别的地方获得。JDK安装程序的文件名不同的版本可能有差异,这里以JDK1.6.0_16为例,它的安装包程序文件名是 jdk-6u16-windows-i586.exe。25
  • 26. JDK安装程序将文件下载到你的计算机某个文件夹,比如“C:\temp”,见下图。26
  • 27. 第二步:运行JDK安装程序。 与执行其他程序一样,用鼠标双击刚才下载的JDK安装程序,开始安装JDK。在安装过程中通常不用人为干预,安装程序会自动安装,当出现提示时只要用鼠标点击“下一步”或“Next”按钮即可。当安装成功结束后,在计算机操作系统所在的磁盘上看到存放Java系统的文件夹,默认安装目录是: C:\Program Files\Java\jdk1.6.0_16 下图显示执行jdk-6u16-windows-i586.exe后JDK的安装目录 。27
  • 28. JDK安装目录28
  • 29. 在JDK安装目录中包含有: 开发工具:(\bin)指工具和实用程序,可帮助您开发、执行、调试和保存以 Java编程语言编写的程序。Java用于运行Java程序,Javac用来把Java源程序(.java)编译成能由Java解释执行字节码程序(.class)。 运行时环境:(\jre)由 JDK 使用的 Java Runtime Environment (JRETM) 的实现。JRE 包括 JavaTM 虚拟机 (JVMTM)、类库以及其他支持执行以 JavaTM 编程语言编写的程序的文件。 附加库:(\lib开发工具所需的其他类库和支持文件。29
  • 30. 演示applet和应用程序:(\demo)JavaTM 平台的编程示例(带源代码)。包括使用 Swing 和其他 Java 基类以及 Java平台调试器体系结构的示例。 样例代码:(\sample)某些 Java API 的编程样例(带源代码)。 C头文件:(\include)支持使用Java本机界面、JVMTM 工具界面以及 Java平台的其他功能进行本机代码编程的头文件。 源代码:(\src.zip)组成 Java 核心 API 的所有类的 JavaTM 编程语言源文件(即,java.*、javax.* 和某些 org.* 包的源文件,但不包括 com.sun.* 包的源文件)。 30
  • 31. 第三步:设置JDK环境变量。 通常JDK安装完成后需要设置Java环境变量PATH和CLASSPATH。(1).PATH变量 是操作系统用于查找可执行文件的目录集,格式如下: PATH=;\bin JDK安装完成以后需要将开发工具的存放目录加入到PATH变量中,使得在编译或执行Java程序时操作系统能够找到编译程序javac或解释程序java。31
  • 32. (2).CLASSPATH变量 是Java编译器编译用于查找相关类或接口的目录集,也是Java解释器用于查找相关类或接口的目录集,格式如下: CLASSPATH=[;...] 这里< jar文件路径名>由每个jar文件及存放它的目录名组成,例如 D:\Program Files\Java\jdk1.6.0_16\lib\dt.jar 多个路径名之间用“;”分隔。32
  • 33. 在Windows系统下设置环境变量可以从控制面板的系统设置添加。这里以JDK1.6为例介绍环境变量的设置过程,假设JDK安装的安装路径是 C:\Program Files\Java\jdk1.6.0_16在控制面板中打开“系统”,选择“高级”标签见图. 然后“环境变量”按钮打开环境设置窗口,见图 .33
  • 34. 在“系统变量”中选择“Path”,然后安下“编辑”按钮弹出“编辑系统变量”窗口。 34
  • 35. 在“变量值”中添加 ;C:\Program Files\Java\jdk1.6.0_16\bin; 最后按下“确定”。35
  • 36. 在“系统变量”中后按下“新建”按钮。 在“变量名”中输入CLASSPATH。在“变量值”中依次输入下列内容 C:\Program Files\Java\jdk1.6.0_16\jre\lib\rt.jar; C:\Program Files\Java\jdk1.6.0_16\lib\dt.jar; C:\Program Files\Java\jdk1.6.0_16\lib\tools.jar; (省略) 按下“确定”。 36
  • 37. Java平台建立(即安装JDK)完成后就可以运行或开发Java程序了。JDK提供了基本的Java开发工具,这些工具放在JDK安装目录下的bin目录。但是,对于复杂大型的Java程序是不能满足要求,需要专门的集成开发工具。下面分别介绍JDK提供主要工具软件,并对目前常用的集成开发工具做简单介绍。(1)JDK开发工具 JDK开发工具包括工具和实用程序,可帮助开发、执行、调试和保存以 Java 编程语言编写的程序。在这些程序中主要工具程序有:编译工具Javac,解释工具Java,文档生成工具,Java平台调试工具等。2.建立Java开发环境37
  • 38. Javac Java编译器,将Java源程序编译成字节码,生成class文件。在bin目录下,文件名称是javac.exe。命令格式: javac [选项] 源文件 [类] [ @argfiles ] 其中, 选 项 – 编译参数。 源文件 – 一个或多个需要编译的java源程序文件。 类 – 一个或多类。 @argfiles – 参数文件。 38
  • 39. 使用示例:编译Java源程序HelloWorldApp.java。 39
  • 40. Java Java解释器,直接从类文件执行Java应用程序,即application。命令格式:java [选项] 类 [参数... ] java [选项] -jar jar文件 [参数... ] javaw [选项] 类 [参数... ] javaw [选项] -jar jar文件 [参数... ] 其中, 选项 – 运行参数。 类 – 被调用的类的名称。 -jar jar文件 – 被调用的jar文件名称。 参数 – 传送给main方法的参数串。40
  • 41. 使用示例:执行Java类HelloWorldApp.class。 41
  • 42. (2)Java集成开发工具 集成开发环境(简称IDE及Integrated Development Environment的缩写)是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面工具。就是集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。所有具备这一特性的软件或者软件套(组)都可以叫做集成开发环境,可以独立运行,也可以和其它程序并用。JAVA的集成开发环境很多,比如 JCreator,NeBeans,Java Studio,JBuilder,Java Workshop,JDeveloper,Visual Age for java,Eclipse等等,这里简单介绍JCreator、netbeans和eclipse。 42
  • 43. JCeator 分为JCeator Le和JCeator Pro两个版本,JCreat Le为免费版,而JCeator Pro要注册。JCreat Le功能不及JCeator Pro。 JCreator Pro是一款适合于各个 Java 语言编程开发人员的IDE工具。它为使用者提供了大量强劲的功能,例如: 项目管理、工程模板、代码完成、调试接口、高亮语法编辑、使用向导以及完全可自定义的用户界面。缺点是只能进行简单的开发,不能进行企业J2EE开发应用。43
  • 44. NetBeans IDE NetBeans是一个全功能的开放源码Java IDE,可以帮助开发人员编写、编译、调试和部署Java应用,并将版本控制和XML编辑融入其众多功能之中。NetBeans 可支持Java 2平台标准版(J2SE)应用的创建、采用JSP和Servlet的2层Web应用的创建,以及用于2层Web应用的API及软件的核心组的创建。此外,NetBeans 最新牒还预装了两个Web服务器,即Tomcat和GlassFish,从而免除了繁琐的配置和安装过程。所有这些都为Java开发人员创造了一个可扩展的开放源多平台的Java IDE,以支持他们在各自所选择的环境中从事开发工作,如Solaris、Linux、Windows或Macintosh。 44
  • 45. 2010年6月16日,Oracle正式发布NetBeans 6.9正式版,将扩大对JavaFX 1.3和OSGi的支持。目前Netbeans的最新版本是Netbeans 6.9.1 可以从官方网上下载安装文件netbeans-6.9-ml-windows.exe,下载网址: http://netbeans.org/ 。Netbeans的安装分为两步: 安装JDK(如果已经安装了JDK可以跳过)。 安装netbeans 6.9.1。运行安装文件即可。如果没有特别的使用要求,安装过程中出现提示时直接点击【Next】或【ok】按钮,直到安装结束。45
  • 46. EclipseEclipse是著名的跨平台的自由集成开发环境(IDE)。最初主要用来Java语言开发,但是目前亦有人通过插件使其作为C++、Python、PHP等其他语言的开发工具。Eclipse的本身只是一个框架平台,众多插件的支持使得Eclipse拥有其他功能相对固定的IDE软件很难具有的灵活性。许多软件开发商以Eclipse为框架开发自己的IDE。 Eclipse的运行需要有Java的虚拟机存在,在编译java的时候不需要额外的编译器。自身就能对java源代码进行编译。由于Eclipse是使用java编写的,所以在跨平台上做的很好,常用的平台Eclipse都能运行。46
  • 47. Eclipse最大的特点使用插件满足使用者根据自己的需要对其进行扩展,且Eclipse源代码进行开放,使插件的数量不断增长,其中不乏一些非常优秀的插件。也使得Eclipse的功能大大增强,使用Eclipse作为基础来开发的软件也很多。47
  • 48. Eclipse的安装分为两步: 安装JDK(如果已经安装了JDK可以跳过)。 到www.eclipse.org下载eclipse,可以选择: Download now: Eclipse SDK 3.2 , Windows (120 MB) 下载完成后,只需要将下载的压缩文件eclipse-SDK-3.2-in32.zip解压到指定位置,例如d:\Eclipse即可完成安装. 安装完成后,eclipse文件夹中的目录结构如图:48
  • 49. 启动eclipse,双击安装目录下的eclipse.exe文件,在启动画面消失后,屏幕将显示一个对话框,提示选择工作空间的目录位置,这个目录用于存放用户创建的项目文档(你自己选一个地方),最后进入Eclipse的工作环境.如图:49
  • 50. 1.5 Java(源)程序结构1.Java程序的构成 Java 程序是由一个或多个编译单元构成,每个编译单元都一个以.java为扩展名的文本文件,又称Java源程序文件。在java编译单元(源程序)中包含几种不同的元素,即:package 语句 import 语句 类(class)声明或接口(interface)声明语句50
  • 51. 一个程序可包括若干个类。 各类之间存在并列、继承和包含关系。 这些类通常是在一起协同工作的。 编程只能在方法中。 类和方法中的语句包含在“{”和“}”之间。 每条语句以分号“;”结尾。 语句由表达式、变量、字面值和关键字构成。 编译后每个类产生一个 .class 文件。51
  • 52. package 包名称; import 包名.类; class 类名1 { 域定义 方法名1() { …… } 方法名2() { …….. } …… } ……52
  • 53. public class LotsHelloApplication { public static void main(String[] args) { for ( int j=0; j<5; j++) { System.out.println(“Hello! World,”); } } }类声明与定义类中的方法语句结尾以分号标志用大括号括起 语句组Java示例程序:LotsHellosApplication . java53
  • 54. 2.Java程序的几种类型Client 机Server 机Browser网页字节码Application(Java应用程序) “Java应用程序”是可以独立运行的Java程序。由Java解释器控制执行。 Applet(Java小程序) “Java小程序”不能独立运行,而是被嵌入到Web页中。由Java兼容浏览器控制执行。54
  • 55. Serverlets Java技术对CGI 编程的解决方案。 运行于Web server上的、作为来自于Web browser 或其他HTTP client端的请求 和 在 server上的数据库及其他应用程序之间的中间层程序。 Serverlets的工作是: 读入用户发来的数据。 找出隐含在HTTP请求中的其他请求信息。 产生结果。 格式化结果(网页)。 设置HTTP response参数。 将文档返回给客户端。55
  • 56. 3.程序类型与用户界面字符界面图形界面ApplicationAppletServerlets56
  • 57. 4. Application程序基本结构public class HelloApplication { public static void main(String args[]) { System.out.println("Hello, Java world! "); } }由一个或多个“类”组成。 其中必须有一个“类”定义了main() 方法,该方法是自动执行的类方法,是Java应用运行的起始点。而这个类也就称之为“主类”。 Java程序源文件名要与主类名同名(包括大小写一个类产生一个.class文件。例如HelloApplication.java。57
  • 58. Application程序上机过程编辑源程序 Edit HelloApplication.java (dos命令) 使用notepad编辑器编辑java源程序更为方便。 编译 — javac javac HelloApplication.java 产生HelloApplication.class 文件 解释执行 — java java HelloApplication (隐含.class文件) 58
  • 59. 5.applet 小程序import java.awt.Graphics; import java.applet.Applet; class HelloApplet extends java.applet.Applet { public void paint(Graphics g) { g.drawString(“Hello, Java World!”, 10,20); } }源程序文件名:HelloApplet.java59
  • 60. 编译java小程序 javac HelloApplet.java 使用文本编辑建立test.html文件,嵌入HelloApplet.class 浏览html文件 使用appletviewer appletviewer test.html 使用常规的浏览器applet 小程序60
  • 61. Application: D:\> edit HelloApplication.java D:\> javac HelloApplication.java D:\> java HelloApplication Hello, Java World!1.6 运行你的第一个java程序1.利用JDK实用工具编写、运行程序1.进入到“命令提示符”。 2.按下图所示顺序操作。61
  • 62. Applet:D:\> edit HelloApplet.java D:\> javac HelloApplet.java D:\> edit test.html D:\> appletviewer test.html62
  • 63. 2.利用集成环境编写、运行程序(略)63
  • 64. 64第二章、Java语言基础基础语言 ( Java程序的构成 )
  • 65. 652.1、Java程序的构成 java 程序是由一个或多个编译单元构成,每个编译单元都一个以.java为扩展名的文本文件,又称Java源程序文件。1.Java程序的组成主程序(类) 源程序(类)1 源程序(类)2 源程序(类)3 …… 源程序(类)nJava 程序
  • 66. 例如 名为CodePointIM的Java程序由三个源文件组成: CodePointIM.java CodePointInputMethod.java CodePointInputMethodDescriptor.java 因为主类的名称是CodePointIM,所以可以此名做为程序的名称。CodePointIMCodePointIM.java CodePointInputMethod.java CodePointInputMethodDescriptor.java66
  • 67. 2.Java源程序的组成package 包名称; import 包名称.类名称; 类或接口声明语句在java编译单元(源程序)中包含几种不同的元素,即:package 语句是可选的。如果有该语句编译器在生成类 文件时会将编译生成的“.class”文件存放到由“包名称”指定的包中。每个源程序中只能有一条package语句,而且必须在第一条语句。 import 语句引入由“类名称”指定的其他类。一个源程序中可以有多条import语句。67
  • 68. 一个程序可包括若干个类,但由 public 修饰的类只能有一个。 各类之间存在并列、继承和包含关系。 这些类通常是在一起协同工作的。 编程只能在方法中。 类和方法中的语句包含在“{”和“}”之间。 每条语句以分号“;”结尾。 语句由表达式、变量、字面值和关键字构成。 编译后每个类产生一个 .class 文件。类或接口声明语句是Java原程序的主体,编写程序的过程实际上就是声明类或接口的过程。68
  • 69. package 包名称; import 包名.类; …… public class 类名1{ 类的成员变量(或域); 方法名(参数) { 局部变量和语句; } …… }下图就是Java源程序的一般形式。69
  • 70. 例 程序Line.javapackage chapt02.shape; import java.awt.Graphics; public class Line { protected int x1,y1; protected int x2,y2; public Line(double x1,double y1,double x2,double y2){ this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public void draw(Graphics g){ g.drawLine(x1,y1,x2,y2); } }包名称引入的类名称类名称Line方法draw方法方法参数70
  • 71. 3.Java源程序文件的命名按Java语言规定,源程序的文件名必须与由 public 修饰的类的类名称相同。例如下面的程序:public class TestFx extends Applet { private Fx fx; public void init() { fx = new Fx(this.getSize().height); } public void paint(Graphics g) { for(int x=0;x
  • 72. 4.Java应用程序(Application)的组成Java应用程序是Java程序中的一种。这类程序具有下面的一些特征: 程序可以独立运行,直接从操作系统启动。 多数应用程序都具有图形用户界面,即GUI界面。 每个程序都具有完整的功能和用途,可以独立完成具体的事务,有明确的应用领域。 程序可能很简单,也可能非常复杂和庞大。72
  • 73. 由一个或多个“类”组成。 其中必须有一个“类”定义了main() 方法,该方法是自动执行的类方法,是Java应用运行的起始点。而这个类也就称之为“主类”。 Java程序源文件名要与主类名同名(包括大小写一个类产生一个.class文件。例如HelloApplication.java。Java应用程序在程序构成上具有下列这些特征:例如下面的程序就是一个Java应用程序。这个程序完成一个数学函数的计算。73
  • 74. 例 Fx程序计算数学函数。源程序文件名:Fx.java。 f(x) a x>0 - a x≤0 public class Fx { public int fx(int x){ if(x>213) return 1; else return 0; } public static void main(String args[]) { Fx y = new Fx(); System.out.println(" f(x)="+y.fx(267)); } }74
  • 75. 关于main()方法main()方法是由解释器或Java虚拟机自动执行的方法,是Java应用运行的起始点。 含有main()方法的类称之为“主类”。当有多个类在同一个源程序时main()方法应放在由public修饰的类。 main()方法的方法声明(格式)必须是: 修饰符public和static没有固定的顺序,但习惯上是 public在前static在后。 参数的类型必须是String [],参数名称可以用任何名字,但习惯上使用args或argv。public static void main(String[] args)75
  • 76. 5.Java小程序(Applet)的组成Java小程序是不能独立运行,是被嵌入到Web页中,由Java兼容浏览器控制执行。在程序结构上它没有像应用程序那样的main()方法,因此它的程序具有如下特征:由一个或多个“类”组成。 由Java兼容浏览器控制执行的类必须是Applet类的子类,它是Java小程序运行的起始点,也就小程序的“主类”。Java程序源文件名要与主类名同名。 在类中根据需要覆盖init()、start()、stop()、destroy()和paint()等方法。 小程序执行由html文件中的实现。76
  • 77. Applet程序的基本结构 import java.awt.*; import java.applet.*; public class 类名 extends Applet { public void init() { } public void stop() { } public void start() { } public void destroy() { } public void paint(Graphics g) { } }77
  • 78. Applet程序的执行Html标记 [78
  • 79. Applet程序示例程序 import java.awt.*; import java.applet.*; public class HelloApplet extends Applet { public void paint(Graphics g) { g.drawString("JavaApplet 欢迎你!!", 50, 60 ); } }这个程序只需简单地显示一个字符串,没有复杂要求,更没有需要初始化的变量或操作,因此只覆盖了paint方法。79
  • 80. 80第二章、Java语言基础基础语言 ( 数据类型、字面量、变量 )
  • 81. 812.2、数据类型、字面量、变量 1.数据类型Java数据类型有: 原始数据类型(Primitive Data Types ) 引用类型(reference type ) Java原始数据类型又称基本数据类型,它说明了在程序中所能表示的基础数据的种类,通常有8种。 引用类型包括类、接口等,具体内容将在后面章节介绍。
  • 82. 82boolean 布尔型,只有真(true)与假(false) byte 8位符号整数,取值范围-128~+127 short 16位符号整数,取值范围-32768~+32767 char 16位字符,Unicode字符集,字符码数值范围 0(‘\u0000’ )~65535(‘\uffff’)。 int 32位符号整数,取值范围: -2147483648~+2147483647 long 64位符号整数,取值范围: -9223372036854775808~+9223372036854775807 float 32位单精度浮点数,使用IEEE754标准。 double 64位双精度浮点数,使用IEEE754标准。 Java原始(基本)数据类型
  • 83. Java原始数据类型变量的默认值数据类型默认值 byte0short0int0long0Lfloat0.0fdouble0.0dchar'\u0000'String (or any object)  nullbooleanfalse83
  • 84. Java原始数据类型占用的位数数据类型占用位数 byte8short16int32long64float32double64char16boolean884
  • 85. 85符号是构成程序的基本单位,一个程序实际上是用特定符号描述的计算机命令集合,这些命令确定存储器分配,完成各种计算和控制。java采用Unicode字符集,使他可以更好的提供多语言支持。java符号可分为如下5种:标识符(Identifiers) 指构成java程序代码中变量、类、方法的名字的符号串。 关键字(Keyword) java语言使用的专用符号。 字面值(Literals) 表示一些具有固定值的常数。 运算符(Operands) 表示算术、逻辑运算的符号。 分隔符(Separator) 空格、值表符、回车换行符等。2.Java符号
  • 86. 86(1)注释 java语言可使用三种格式的注释。//注释内容 从//到行末的内容被忽略 /*注释内容*/ 在/* 和 */之间的内容 /**注释内容*/ 同上 /* @(#)Sample3_3.java 1.0 01/10/22程序计算一个梯形 */ public class Sample3_3{ int L1,L2; //上下底边 int H; //高 …… }注释注释
  • 87. 87(2)标识符 标识符构成java程序代码中变量、类、方法和接口的名字,这些名字是唯一的。java语言所有标识符是由字符组成的字符串,构造标识符遵循下面的规则:标识符必须以字母、下画线或‘$’符号为第一个字符。 后续字符可以是数字‘0’-‘9’,其他非保留字字符。 java语言中大小写是有区别的。例如, int ox,oy; String $name,_year; 都是正确的标识符,在此表示变量名称。
  • 88. 88(3)关键字 所谓关键字是指java语言使用的标识符,又称保留字。例如下面列出的几个关键字。关键字描 述abstract定义抽象boolean定义布尔变量break结束/终止byte8位整数类型caseswitch语句的一个选择catch捕获异常char字符类型(16位)class定义类
  • 89. 89字面值是源代码固定值的表示。java中的字面值区分为不同的数据类型,通常有: 整型 实型 字符 布尔 字符串 空对象3.字面值(常量)89
  • 90. 90(1)整型字面值,有三种表示形式:八进制 :以0开头只能出现数字0~7,例如 0126,0453等。十六进制:以0x开头的整型数,可以包括数字0~9,字母a~f或A~F,例如 0x12AD,0x9FFDBD等。十进制 :由第一个字符不为‘0’的数字串组成,例如 234、122、657489等。 90
  • 91. 91(2)浮点型 字面值,用十进制表示,主要由三部分组成:整数、小数点‘·’、小数部分、指数和类型后缀。小数表示: 整数.小数 指数表示: 整数.小数[±E指数] 整数.小数[±e指数]例如:4.0987 3.12E34 3.678E-12用在小数后加后缀d或D,表示double型浮点数;在小数后加后缀f或F,表示float型浮点数。 例如,2.0D、2.0d 是double型浮点数; 2.0f、2.0F 是float型浮点数。91
  • 92. 92(3)布尔型字面值,有两个值:true(真)、false(假)。 (4)字符型字面值,由单引号括起的字符。 例如 ‘Q’,’P’,’天’等。 Java采用Unicode字符集,因而每个字符占用16位,可表示0~65535之间的字符码。 转义字符:\b 退格 \‘ 单引号 \t 水平制表符 \\ 反斜线 \n 换行 \f 表格符 \r 回车 \” 双引号92
  • 93. (5)空对象字面值,表示形式:null。 它常用来作为对象是否可用的 标记。(6)class字面值,表示形式:类型名称 .class。例如: String.class Integer.class 等。93
  • 94. 94对象存储它的状态在域(Field)中,变量也是存储程序中数据的,它们都是通过一个名字引用值。在Java语言中域(field)和变量(variable)都使用,因此会引起一些混乱,原因是它们通常具有相同的含义和用途。4.变量(域)(1)变量命名: 是一个合法的标识符,它是字母、数字、下划线或美元符“$”的序列,Java对变量名区分大小写,变量名不能以数字开头 ,而且不能为保留字 。 合法的变量名如:myName、 value-1、 dollar$等 。非法的变量名如: 2mail、room#、 class (保留字)等,变量名应具有一定的含义,以增加程序的可读性 。94
  • 95. 95(2) 变量类型: 可以为上面所说的数据类型中任意一种数据类型 。 (3) 变量的作用域: 声明一个变量的同时也就指明了变量的作用域。java规定允许变量在任何代码块中声明,一个代码块由大括号{…}括起的代码。按作用域来分,变量可以有下面几种: 实例变量(Instance Variables)即非静态域(Non-Static Fields )。 类变量(Class Variables)即静态域(Static Fields )。 局部变量(Local Variables )。 参数(Parameters)。 95
  • 96. 96 实例变量(Instance Variables): 非静态域(Non-Static Fields),声明时不用static修饰的域。对象存储它的个体状态在非静态域中,非静态域也被称做“实例变量”,它们的值对于一个类的每个实例是唯一的。实例变量public class Circle { static final MIN_RADIUS=1; protected int m_radius; protected int m_ox,m_oy; public Color m_color; …… …… }96
  • 97. 类变量(Class Variables): 类变量是声明时用static修饰的域,不管类被实例化多少次(也就是创建多少个对象),类变量仅有一个,即类的多个实例(对象)共享类变量。public class Circle { static final MIN_RADIUS=1; protected int m_radius; protected int m_ox,m_oy; public Color m_color; …… …… }实例变量类变量97
  • 98. public class Cuboid{ public String toString(){ String msg="\nCuboid 对象成员\n length :"+length; msg+="\n width :"+width+"\n high :"+high; return msg; } public static void main(String []argc){ Cuboid c1=new Cuboid(); System.out.println(c1.toString()); } } 局部变量(Local Variables ) : 在方法中保存临时状态值的变量即局部变量。Java语言没有专门的关键字指明一个局部变量,它声明在方法开始符号“{”和结束符号“}”之间。局部变量仅在声明它的方法中有效,类中的其他方法是不能使用的。局部变量局部变量98
  • 99. 参数(Parameters) : 是在方法中传递给方法数据的变量,它在方法参数表中声明,它的作用域就是这个方法。 下面的程序中main方法有一个参数argc。方法参数public class MemberVariable{ …… public static void main(String []argc){ MemberVariable mv=new MemberVariable(); mv.printValue(); } …… } 99
  • 100. 100成员变量范围方法参数范围局部变量范围例外处理参数范围变量在类中位置100
  • 101. 在程序中使用变量时,必须明确提供变量的名称和类型。变量名称是一个合法的标识符——以字母开始的长度无限的Unicode字符序列。变量是Java程序中数据的基本存储单元,变量通过一个名字引用值,即包含在变量中的数据。变量类型决定了它保存的值以及可以实现的操作。使用变量前必须声明变量,它的声明语法格式: (4) 变量声明:变量类型 变量名称[=初始值] [ , ……];“变量类型” 即变量的数据类型,变量的数据类型可以是基本类型,也可以是类、接口等复杂的引用型。101
  • 102. “变量名称”声明的变量的名称,如果声明多个变量,每个变量间用“,”隔开。 “=初始值” 如果在定义变量时需要给变量确定数值,可以用“=”为变量赋值。 例如 boolean startFlag = false; boolean opened , runnable; byte c1 , c2 = ‘A’ , c3 = ‘\n’; short size; int width , length; long scroe; float year , size = 0.45f; double height , sum ,;102
  • 103. public class MaxVariables { public static void main(String args[]) { byte largestByte = Byte.MAX_VALUE; short largestShort = Short.MAX_VALUE; int largestInteger = Integer.MAX_VALUE; long largestLong = Long.MAX_VALUE; float largestFloat = Float.MAX_VALUE; double largestDouble = Double.MAX_VALUE; char aChar = 'S'; boolean aBoolean = true; System.out.println("变量名称 变量值"); 例 变量声明并显示数据类型的最大值。103
  • 104. 104 System.out.println("-------- ------------------"); System.out.println("byte = "+largestByte); System.out.println("short = "+largestShort); System.out.println("integer = "+largestInteger); System.out.println("long = "+largestLong); System.out.println("float = "+largestFloat); System.out.println("double = "+largestDouble); if(Character.isUpperCase(aChar)) { System.out.println("character = "+aChar+" is uppercase"); } else { System.out.println("character = "+aChar+" is lowercase"); } System.out.println("aBoolean = " +aBoolean); } }104
  • 105. 程序执行结果如下: 变量名称 变量值 -------- ------------------ byte = 127 short = 32767 integer = 2147483647 long = 9223372036854775807 float = 3.4028235E38 double = 1.7976931348623157E308 character = S is uppercase aBoolean = true105
  • 106. (5) 变量初始化:局部和成员变量定义后必须赋予初值才能使用,即所谓的“初始化”。初始化变量是把一个常量或表达式的结果赋给变量,赋值通过“=”运算符实现,可以在定义变量时或通过赋值语句完成这个过程。参数和例外处理参数不能这样初始化,它们的值是在方法或例外处理被调用时由调用者传递。下面给出初始化变量的简单格式:类型 变量名1=常量或表达式 [,……]; 或 变量名 = 常量或表达式;106
  • 107. 数据类型默认值数据类型默认值booleanfalselong0byte 0float0.0char 空字符'\0'double0.0short 0引用nullint 0成员变量当被声明后,编译器会自动为它们设置一个默认初值。下表给出变量的默认初值。 107
  • 108. 108第二章、Java语言基础基础语言 ( 语句、运算符和表达式 )
  • 109. 1092.3、语句、运算符和表达式1.语句(Statements)(1)语句 语句是构成Java程序的基本单位之一,一条语句形成完整的可执行单元。 每条语句都以“;”结束,语句构成符合Java语法规则。 语句必须包含在类、方法和代码块,即必须在由“{”和“}”括起来。 在类中只能包含类的属性声明语句,其他的执行语句必须放在类的方法中。
  • 110. …… public class 类名1{ 类的成员变量(或域)声明语句; …… 方法名(参数) { 局部变量说明语句; …… 表达式或控制流程语句; …… } …… }下图表示Java源程序类中语句形式。110
  • 111. 表达式语句 完成给变量赋值、算术运算、逻辑运算等。例如 x=100; F=(1/(x*x*x))+(1/(x*x))+ (1/(x)); 声明语句 声明类或接口的成员变量或域,声明局部变量等 。例如 private double width,color; …… int number; String name,code; ……(2)Java语句的基本类型:在Java语言中,语句的基本形式有三种,它们是:111
  • 112. 控制流程语句 根据条件和逻辑表达式控制程序执行流程。例如 …… If(runnable){ while(getTime()<=0.156){ time=systemTime()/1000.0; count++; } }else{ time=systemOutTime(); count=0; }112
  • 113. 空语句 由一个“;”构成的语句,这种语句不做任何有实际意义的操作。例如 System.gc(); ; System.exit(0); 方法调用语句 调用对象或类的方法,用于完成某项操作或功能。例如 …… mainframe.size(800,600); mainframe.setVisible(true); ……除了这三种基本形式外,程序中还会有三种形式,即空语句、方法调用语句和代码块语句。113
  • 114. 代码块语句 即必须在由“{”和“}”括起来的语句组,又称复合语句。例如 int nextNumber = 0; …… { int nextNumber = 3000; newNumber = Math.sqrt(Number); } …… static { thirdNumber = 5.09e+4; }114
  • 115. public class StatementSample { int fib(int n) { if(n < 2) return 1; return (fib(n - 2) + fib(n - 1)); } public static void main(String[] args) { StatementSample f = new StatementSample(); int k = 6; System.out.println("First " + k); for(int i = 0; i < k; i++) System.out.println("fib("+i+")="+f.fib(i)); } }下面通过一个Java源程序来解释在类中语句形式,程序文件名称:StatementSample.java115
  • 116. StatementSample.java执行结果116
  • 117. 代码块,用花括号括起来的语句组,包含0条或多条语句,它可以做为单条语句那样被用在任何允许的地方。考察下面的程序:2.代码块(Blocks ) if (condition) { System.out.println("Condition is true."); } else { System.out.println("Condition is false."); }代码块1代码块2117
  • 118. 算术运算符 关系运算符 移动和位逻辑运算符 赋值运算符 其他运算符运算符3.表达式 表达式是一个由变量、常数、运算符和方法调用等,按照语言语法构造的符号串。Java语言提供丰富的运算符,按照它们用途可以将其分为:118
  • 119. 表达式计算是Java程序的任务之一。通常,表达式用于计算并赋值给变量,或帮助控制程序的执行流程。表达式的计算过程包括两步骤:计算表达式和返回计算结果,因此每个表达式必定有它自己的计算结果值。考察表达式:(K+M)*S,其中K=20.45,M=0.55,S=5.0。(1)表达式的任务(K+M)*S(K+M)*S (20.45+0.55)*S 21.0*S 21.0*5.0 105.0计算105.0返回结果119
  • 120. 表达式由变量、运算符和方法调用按照语言语法构造而成。 表达式有唯一的结果值,它的数据类型依赖于组成表达式的各个元素。 Java语言允许构造复杂表达式,在执行计算操作过程中,按照运算符的优先级别和结合性进行计算。 (2)表达式的组成考察下面表达式的执行过程:45+55.0*1-2/1.0其中45、1、2是int常量,55.0、1.0是double常量,因此在计算过程中还要进行数据类型转换。120
  • 121. 45+(55.0*1)-2/1.0 计算:55.0*1 →55.0 45+55.0-(2/1.0) 计算:2/1.0 →2.0 (45+55.0)-2.0 计算:45+55.0 →100.0 (100.0-2.0) 计算:100.0-2.0 →98.0 (98.0) 表达式结果 →98.0在计算中,有乘法、加法、减法和除法运算。按照算术运算规则,先乘除法运算,后加减发运算。对于优先级别相同的运算,Java规定从左到右依次计算。所以表达式的计算过程:乘法,除法,加法,减法。另外在计算过程中会自动进行数据类型转化,即int->double。下面列出表达式的计算过程:121
  • 122. (3)表达式计算的优先顺序和结合性 .[]() 左/右 高 单目运算 右 */% 左 +- 左 ↓ 移位运算 左 < <= > >= 左 == != 左 & 左 低 ^ 左 | 左 && 左优先级 运算符 结合性优先级 运算符 结合性高 || 左 ↓ ?: 右 低 赋值 右 122
  • 123. 123java语言限制使用强制类型转换,以防止因错误而导致系统崩溃。数据类型的转换应以可兼容为原则,如果类型兼容则可以自动转换,可完成自动转换的条件: 两个数据类型兼容。 将占用存储空间小的数据转换成占用存储空间大的数据类型。 数值类型是相互兼容(整数和浮点数)的,但数值类型与字符类型和布尔类型则不兼容。对于不兼容的数据类型可以在其之间进行强制转换,强制转换的通常用如下方式: ( 类型 ) 变量值或表达式 (4)表达式计算中数据类型转换
  • 124. 124public class TypeChange { public static void main(String arvg[]) { byte b; int i=256; double d=257.142; b=(byte)i; System.out.println(“b=”+i); i=(int)d; System.out.println(“i=”+i); b=(byte)d; System.out.println(“b=”+b); } }例数据类型转换执行结果: b=256 i=257 b=1124
  • 125. 赋值运算符用于把一个值分配另外一个操作数。由赋值运算符构成的表达式称作“赋值表达式”,它的基本形式:4.赋值表达式变量或对象 = <表达式>其中,“=”是赋值运算符。左边只能是变量或对象。右边可以是:算术表达式。 例如 Sum = (endNumber-beginNumber)*unitSize Income = (m1+m2+m3+m4+m5+m6)*rise125
  • 126. 关系条件表达式。例如 doorState=(switch==true)&&(!power) 方法调用。例如 newInstanc=DataBuiler.createNewInstance() …… shapeColor=newInstance.getColor() …… 对象创建。例如 JPanel pane; pane = new JPanel() JButton button; button = new JButton(“确认”)126
  • 127. 赋值表达式以“;”结束时,就构成一条赋值语句,语法格式:变量或对象 = <表达式>;5. 赋值语句它的基本形式与赋值表达式类似,只不过是以“;”结尾。算术表达式。 例如 Sum = (endNumber-beginNumber)*unitSize ; Income = (m1+m2+m3+m4+m5+m6)*rise ;127
  • 128. 关系条件表达式。例如 doorState=(switch==true)&&(!power) ; 方法调用。例如 newInstanc=DataBuiler.createNewInstance(); …… shapeColor=newInstance.getColor(); …… 对象创建。例如 JPanel pane; pane = new JPanel() ; JButton button; button = new JButton(“确认”) ; 128
  • 129. 129public class CircularArea { public static void main(String[] args) { double radius; double area; radius = 310; area = radius * radius * Math.PI; System.out.println(“圆的面积是 " + area); } }例 计算半径为310米圆的面积。圆面积是301907.0540099791结果:129
  • 130. 6.复杂赋值运算表达式赋值运算符与其他运算符结合就构成所谓“复杂赋值运算”。在运算符左边的变量参与右边表达式的运算,结果仍然返回给左边的变量,这类运算符包括:+=、-=、/=、%=、&=、|=、^= 、<<=、>>=、<<<=。 复杂赋值运算过程的赋值表达式就是“复杂赋值运算表达式”,其语法格式:变量或对象 运算符= <表达式>复杂赋值运算表达式构成的语句语法格式:变量或对象 运算符= <表达式> ;130
  • 131. 考察示例计算 M=1+2+3+4+5+6,其中M的初值为0。简单的计算语句如下: M += 1; 等价与 M = M+1; M += 2; 等价与 M = M+2; M += 3; 等价与 M = M+3; M += 4; 等价与 M = M+4; M += 5; 等价与 M = M+5; M += 6; 等价与 M = M+6; 其他复杂赋值运算用法与上述示例相同,具体在下面用简表列出。131
  • 132. 运算符用法描述+=op1 += op2 op1 = op1 + op2 -=op1 -= op2 op1 = op1 - op2 *=op1 *= op2 op1 = op1 * op2 /=op1 /= op2 op1 = op1 / op2 %=op1 %= op2 op1 = op1 % op2 &=op1 &= op2 op1 = op1 & op2 |=op1 |= op2 op1 = op1 | op2 ^=op1 ^= op2 op1 = op1 ^ op2 <<=op1 <<= op2 op1 = op1 << op2 >>=op1 >>= op2 op1 = op1 >> op2 >>>=op1 >>>= op2 op1 = op1 >>> op2 复杂赋值运算用法简表132
  • 133. 7.示例从键盘输入两个整数,分别表示一个三角形的高和底边长度,然后计算该三角形的面积。分析: 根据三角形的面积计算公式 :面积=底边长×高÷2 可知面积的计算方法,需要定义一个变量存放费面积值。计算公式中有除法运算,求出的面积值不是整数,因此这个变量需要用float或double。 程序要求键盘输入底边和高度值,因此需要设定两个变量分别存放这两个数值。因为题目已经指出它们是整数,所以用int和long都可以。 键盘输入用Scanner类提供的方法从键盘获得数据。133
  • 134. 134import java.io.*; import java.util.*; public class TriangleArea { public static void main(String[] args) { Scanner sc; int height,width; double area; sc = new Scanner(System.in); System.out.println(" "); System.out.print(“请输入底边宽度(米):"); width = sc.nextInt(); System.out.print(“请输入高度(米):"); height = sc.nextInt(); area = (width*height)/2.0; System.out.println(“三角形的面积是”+area+“平方米"); } }
  • 135. 135
  • 136. 136第二章、Java语言基础基础语言 ( 算术运算符和算术表达式 )
  • 137. 1372.4、算术运算符和算术表达式1.算术运算符Java语言支持多种算术运算符。利用这些运算符可以完成浮点数和整数的计算。按照运算符计算所需要的参与运算的数据项数目,这些运算可分为: 二元算术运算 包括:加法(+)、减法(-)、除法(*、)乘法(/)和取余(%)。 一元算术运算 包括:自增(++)和自减(--)。
  • 138. 2.二元算术运算表达式 所谓二元运算就是参与运算的数据项有两项。Java的二元算术运算符有+(加)、-(减)、*(乘)、/(除)和%(求模)。运算表达式的语法格式:例如 56 + 44 100.09 – 24 77 * 54 8921/4 35%5数据项 1 数据项 2 + - * / %138
  • 139. 表达式结果的数据类型由参与运算的数据项的类型确定。 运算过程中如果数据项的类型不同,会先自动进行类型转换时每个数据项的类型相同,然后再进行计算。 在类型转换时,将把占据内存小的数据类型转换为占据内存大的数据类型。 表达式的数据类型是表达式中占据内存大的数据项的类型。(1)二元算术运算中的数据类型139
  • 140. 考察下面表达式在计算过程中数据类型发生的变化。 表达式1: 21+34 21和34数据类型相同,都是int类型常量,所以计算中进行类型转换,最后的结果也是int型。 表达式2: 21.0+34 21.0是double类型常量,34是int类型常量,数据类型不相同,计算中需进行类型转换。 21.0 + 34 将34转换成 double类型 21.0 + 34.0 两个double类型数相加 55.0 仍然为double类型 最后的结果是double类型。140
  • 141. (2) +(加)运算符语法:op1 + op2运算: 计算op1与op2的和。 连接字符串。示例:56 + 66.90 0.12e+7 + 3.16 12L + 1L 2100.03 + 12L “This is “ + “The Java” “Value “ + 2010122.9 1200003.16 13 2112.03 This is The Java Value 2010141
  • 142. (3) -(减)运算符语法:op1 - op2运算: 计算op1与op2的差。 示例:56 - 66.90 0.12e+7 - 3.16 12L - 1L 2100.03 - 12L-10.900000000000006 1199996.84 11 2088.03142
  • 143. (4) *(乘)运算符语法: op1 * op2运算: 计算op1与op2的乘积。 示例:56 * 66.90 0.12e+7 * 3.16 12L * 1L 2100.03 * 12L3746.4000000000005 3792000.0 12 25200.36143
  • 144. (5)/(除)运算符语法: op1 / op2运算: 计算op1 被 op2除。 说明: 如果op1与op2数据类型相同,结果值的数据类型与两者中占据内存多的相同。 如果op1与op2是整数类型,结果值也为整数,小数部分将被截去。 如果op1与op2一个是float或double,另一个是整数,结果值也为float或double类型。144
  • 145. 示例:6 / 23 0.12e+7 / 3.16 12L / 1L 2100.03 / 12L0 379746.83544303797 12 175.00250000000003145
  • 146. (6)%(求模)运算符语法: op1 % op2运算: 计算op1被op2除的余数。 说明: 求模运算时op1与op2必须是整数。 如果op1为负数,op2为正数,结果为负。 如果op1为正数,op2为负数,结果为正。146
  • 147. 示例:56 % 66 -7 % 3 7 % -3 -21 % -1256 -1 1 -9147
  • 148. 运算符用法描述+op1 + op2计算op1与op2的和。 连接字符串。-op1 - op2计算op2与op1的差。*op1 * op2计算op1与op2的乘积/op1 / op2计算op1 被op2除%op1 % op2计算op1被op2除的余数(7)二元算术运算符简表148
  • 149. 3.一元算术运算符 所谓一元运算就是参与运算的数据项只有一项。Java的一元算术运算符有++(自增)、--(自减)、-(求相反数)。运算表达式的语法格式:数据项 + + - -数据项 + + - - -格式1 (前缀)格式2 (后缀)自增和自减运算做为单独表达式时,运算符在数据项的前或后是没用区别的。 如果包含在复杂的表达式内,运算符在数据项的前或后会有不同的结果。 后缀优先级高于前缀。149
  • 150. (1)++(自增)运算符语法:++op(前缀)运算: 把 op 的值增加1。 先将op的值增加1,然后再取op的值作为(++op)结果值。 示例:int x = 2 ++x int a = 2 (++a)*3 3 9150
  • 151. 语法:op++ (后缀)运算: 把op的值增加1。先取op的值作为(op++)结果值,然后再将op的值增加1。示例:int x = 2 x++ int a = 2 (a++)*3 3 6151
  • 152. (2)--(自减)运算符语法:--op(前缀)运算: 把op的值减少1。 先将op的值减少1,然后再取op的值作为(--op)结果值。语法:op-- (后缀)运算: 把op的值减少1。先取op的值作为(op--)结果值,然后再将op的值增加1。152
  • 153. (3)-(求相反数)运算符语法:- op运算: 求op的相反数。示例:int x = 2 -x int a = 2 (-a)*3 -2 -6153
  • 154. (4)Java 一元算术运算符简表 运算符用法描述++op++ (后缀)把op的值增加1。先取op的值作为(op++)结果值,然后再将op的值增加1。++++op(前缀)把op的值增加1。 先将op的值增加1,然后再取op的值作为(++op)结果值。--Op-- (后缀)把op的值减少1。先取op的值作为(op--)结果值,然后再将op的值增加1---- op(前缀)把op的值减少1。 先将op的值减少1,然后再取op的值作为(--op)结果值。-Op求op的相反值。154
  • 155. (5)Java 一元算术运算符示例设int 型变量x和y,且 x=2。分别计算下列表达式: y = (++x) + (++x) y = (++x) + (++x) + (x++)x=4 y=(++x)+(++x)=7 x=5 y=(++x)+(++x)+(x++)=11结果:155
  • 156. 算术表达式执行操作并返回一个值。在执行操作过程中,是按照运算符的优先级别和结合性进行的。下表列出运算符的优先级别:4.算术运算符优先级运算符优先一元后缀 op++ op--一元前缀 ++op --op +op -op 乘除运算* / %加减运算+ -156
  • 157. 157157第二章、Java语言基础基础语言 (关系与条件、位运算)
  • 158. 1581582.5、Java关系与条件、位运算关系运算符用于比较两个值并决定他们之间的关系。关系运算符构成关系表达式,表达式的结果是一个boolean类型的值:true(真)和 false(假)。运算符有:<、 <=、 >、 >=、 ==、 !=。 条件运算符用于与关系运算符组合成复杂的关系表达式,表达式的结果也是boolean类型的值。运算符:&&、 ||、 !、?:。 一般运算是把运算对象作为一个整体处理,而位运算是把整型数运算对象拆开,以位(bit)作为运算对象。运算符: &、 |、 ^、~、>>、 <<、 >>>。
  • 159. 1591.关系运算表达式关系运算符用于比较两个值并决定他们之间的关系。用于测试一个数据项另一数据项是否相等或不相等,高于或低于等关系。它们和相应的数据相构成关系表达式,语法格式:其中Op1和Op2可以是变量、常数或方法调用。运算符包括:==,!=,>,<,>=,<=。该运算的结果是boolean量,即 true 或false。下表列出Java关系运算符。 Op1 运算符 Op2
  • 160. 160运算符用法描述>op1 > op2 如果op1大于op2,返回true。>=op1 >= op2 如果op1大于且等于op2,返回true。
  • 161. 161例3-5-1 int x=5,y=7; boolean relat; relat = x > y; relat = x >= y; relat = x < y; relat = x <= y; relat = x == y; relat = x != y;(源程序文件ch03_5_1.java)
  • 162. 162例3-5-2 从键盘输入两个double数,判断它们之间的关系。 (源程序文件ch03_5_2.java)import java.util.*; import java.io.*; public class ch03_5_2{ public static void main(String []argc){ Scanner sc = new Scanner(System.in); double x,y; System.out.print("输入第一个数:"); x = sc.nextDouble(); System.out.print("输入第二个数:"); y = sc.nextDouble();转下页
  • 163. 163 boolean relat; relat = x > y; System.out.println("结果:"); System.out.println(" " + x + " > " + y + " " + relat); relat = x >= y; System.out.println(" " + x + " >= " + y + " " + relat); relat = x < y; System.out.println(" " + x + " < " + y + " " + relat); relat = x <= y; System.out.println(" " + x + " <= " + y + " " + relat); relat = x == y; System.out.println(" " + x + " == " + y + " " + relat); relat = x != y; System.out.println(" " + x + " != " + y + " " + relat); } }接上页
  • 164. 164
  • 165. 1651652.条件运算表达式条件运算符用于与关系运算符组合成复杂的关系表达式,语法格式:其中 op1 op2 op 可以是变量、常数或方法调用。“运算符”包括:&&,||,!,?:。其中&&和||运算的结果是boolean量,即“true”或“false。下表列出Java条件运算符。 Op1 运算符 Op2 运算符 Op
  • 166. 166条件运算符用法简表运算符用法描述&&op1&&op2 如果op1和op2都是true,则返回true。||op1||op2 如果op1或op2是true,则返回true。!!op 如果op是false,则返回true。?:op1?op2:op3op1为true,则取op2值,否则取op3的值。
  • 167. 167(1)&&(逻辑与)运算规则op1运算符op2结果true&&truetruefalsetruefalsetruefalsefalsefalsefalsefalse例如 1>0 && 4<=5 true 10>23 && 50>6 false 10==10 && 4<=3 true
  • 168. 168(2)||(逻辑或)运算规则op1运算符op2结果true||truetruefalsetruetruetruefalsetruefalsefalsefalse例如 1>0 || 4<=5 true 10>23 || 50>6 true 10!=10 || 4<=3 false
  • 169. 169(3)!(逻辑非)运算规则运算符op结果!truefalsefalsetrue例如 !(4<=5) false !(50<6) true !(10==10 && 4<=3) true
  • 170. 170例3-5-3 从键盘输入1个long型整数,判断它能否被13和27整除。 (源程序文件ch03_5_3.java)分析: 假设有整数M,如果要使M可以同时被13和 27整除(假定这样的数存在),那么必须满足M/13的余数和M/27的余数均为0,即:M%13==0 且M%27==0。写成Java条件表达式就是: (M%13==0 ) && (M%27==0) 下面为实现此任务的程序。
  • 171. 171import java.util.*; import java.io.*; public class ch03_5_3{ public static void main(String []argc){ Scanner sc = new Scanner(System.in); boolean result; long m; System.out.print("输入整数:"); m = sc.nextLong(); result = (m%13==0) && (m%27==0); System.out.println("结果:"); System.out.println(" "+m+"被13整除且被27整除:" + result); } }
  • 172. 172例3-5-4 执行下列语句,检查变量x,y,b值的变化。 int x=3,y=5; boolean b; b=x>y && x++==y--; (源程序文件ch03_5_4.java)(4)&& 与||的“短路”特征所谓短路,就是一旦能够准确无误地得到表达式的结果,就不再继续进行后面运算符的计算。例如 (x<0)&&(y<0) 当 x>=0 时结果一定为false,因此就不再计算y<0。只有当x<0时才继续计算y<0。
  • 173. 173public class ch03_5_4{ public static void main(String []argc){ int x=3,y=5; boolean b; b=x>y && x++==y--; System.out.println("½á¹û£º"); System.out.println("b="+b); System.out.println("x="+x); System.out.println("y="+y); } }
  • 174. 174逐位(bitwise)运算是把操作数按二进制位进行逻辑运算。语法格式:3.逐位运算表达式Op1 运算符 Op2 运算符 Op其中 op1,op2,op 可以是变量、常数或方法调用。运算符包括:&,|,^。 逐位运算仅用于整数型和字符型,以数的二进制位为基本单位。下表列出Java使用的逐位运算符。
  • 175. 175运算符用法描述&op1 & op2 按位与运算。即1&1 = 1, 1&0=0。|op1 | op2 按位O或运算。即0&1 = 1, 0&0=0。∧op1 ^ op2 按位异或运算。即1&1 = 0, 1&0=1。~~op 按位求反运算。即 ~1 = 0, ~0 = 1。 逐位运算符用法简表
  • 176. 176(1)&(与)运算规则位运算符位结果1&11100010000例如 两个byte类型的数 34与23逐位“与”运算,即: 34 & 23 结果为 2。 00100010 & 00010111 00000010
  • 177. 177(2)|(或)运算规则位运算符位结果1|11101011000例如 两个byte类型的数 34与23逐位“或”运算,即: 34 | 23 结果为 55。 00100010 | 00010111 00110111
  • 178. 178(3)∧(异或)运算规则位运算符位结果1∧10101011000例如 两个byte类型的数 34与23逐位“异或”运算,即: 34 ∧ 23 结果为 53。 00100010 ∧ 00010111 00110101
  • 179. 179(4)~(求反)运算规则运算符位结果~1001例如 两个byte类型的数 34和23分别逐位“求反”运算,即: ~34 和 ~ 23 。 ~ 00100010 ~ 00010111 11011101 11101000
  • 180. 180例3-5-5 执行下列语句,检查变量b值的变化。 int x = 3,y = 5; int b; b = x&y; b = x|y; b = x^y; b = ~x; (源程序文件ch03_5_5.java)
  • 181. 181public class ch03_5_5{ public static void main(String []argc){ int x = 3,y = 5; int b; System.out.println("xy="+x+" y="+y); b = x&y; System.out.println("x&y="+b); b = x|y; System.out.println("x|y="+b); b = x^y; System.out.println("x^y="+b); b = ~x; System.out.println(" ~x="+b); } }
  • 182. 1824.位移运算表达式移位操作符执行通过按位左移动或右移动处理数据。Java语言提供三种位移动操作符:<< 、 >> 和 >>>。语法格式:Op 运算符 cnt 其中 Op 可以是变量、常数用。“运算符”包括:>>,<<,>>>。Cnt是移动的位数,必须是一个正整数。下表列出Java使用的逐位运算符。
  • 183. 183移位运算符用法简表运算符用法描述<>op1 >> op2 将op1的每位向右移动op2位,左边空出的位用原来最左(高)位填充。>>>op1 >>> op2 将op1的每位向右移动op2位,左边空出的位用0填充。
  • 184. 184 1 1 0 1 0 1 1每位右移动每位左移动数值按位移动在表中操作符“>>”、“<<”和“>>>”将数据值按位移动若干位,所谓按位移动是把一个具有固定位数的二进制整数向左或向右移动,如图所示:移位操作示意图
  • 185. 185例如,整数5643和-99877分别按位右移8,即: 5643>>8 结果是:22 (二进制数: 1011000001011B 右移8位) -99877>>8 结果是:-391 (二进制数:11111111111111100111100111011011B 右移8位)
  • 186. 186186例3-5-10 计算下列表达式的值: int a=10,b=7,c=-1,d=27,e=-50; int f; f=a>>2; f=b<<4; f=c>>5; f=(a&c)<<3; f=(~(c^d))>>>b; (源程序文件ch03_5_10.java)
  • 187. 1871875.类型比较(instanceof )instanceof 运算符比较一个对象与一个指定的类型。可以使用它测试一个对象是否是一个类的实例,或者是一个子类的实例,或是实现实际接口类的实例。语法格式:运算的结果是boolean量,即true或false。 例如,TextField name; boolean b1= name instanceof TextField; boolean b2= name instanceof String; 结果 b1=true,b2=false; 对象 instanceof 类(子类)名
  • 188. 1881886. Java关系与条件、位运算优先级别! ~ instanceof 右 << >> >>> 左 < <= > >= 左 == != 左 & 左 ^ 左 | 左 && 左 || 左 ?: 右运算符 结合性
  • 189. 189189运算符优先后缀expr++ expr--一元++expr --expr +expr -expr ~ !乘除* / %加减+ -移位<< >> >>>关系< > <= >= instanceof等于== !=算术运算、关系条件和位运算优先级别转下 页
  • 190. 190运算符优先逐位与&逐位异或^逐位或|逻辑与&&逻辑或||条件? :赋值= += -= *= /= %= &= ^= |= <<= >>= >>>=接上 页
  • 191. 191191第二章、Java语言基础基础语言 (条件选择语句 )
  • 192. 1921922.6、条件选择语句 控制流程语句用于控制程序的执行流程,以便根据程序的不同状态进行处理。java语言的控制流程语句分为三类: 选择、 重复 跳转。 选择语句根据表达式或变量的不同状态选择不同的执行路线。条件语句有三种,即if、if…else和switch形式。
  • 193. 1931931.if语句if 语句是所有控制语句中最基础的语句。它告诉我们的程序仅在一个指定的测试求得的值为true时执行某段代码。如果测试求得的值为false时就控制跳过这个程序段。if 语句的语法格式: if( <表达式> ) { 语句; }语句中<表达式> 是一个条件表达式,如果<表达式>的值为真(true),则执行该语句,否则跳过。 if 语句控制代码块,所以用if用具控制的语句组要用“{…}”括起来。
  • 194. 194<表达式>语句truefalseif 语句执行流程图。
  • 195. 195例如,n=getNextNumber(); m=0; if(flage==true && i>1){ n=getInitNumber(); m=1; }例 ch03_6_1 从键盘输入两个double数分别存入变量x和y,判断它们之间的关系。如果x小于y就提示“x小于y”;如果x大于y或等于y就提示“x大于y或等于y”。(源程序: ch03_6_1.java)
  • 196. 196import java.util.*; import java.io.*; public class ch03_6_1{ public static void main(String []argc){ Scanner sc = new Scanner(System.in); String msg; double x,y; System.out.print(“输入第一个数:"); x = sc.nextDouble(); System.out.print(“输入第二个数: "); y = sc.nextDouble(); msg = “小于"; if(x > y){ msg = “大于或等于"; } System.out.println(" x=" + x + " y= " + y + " x" + msg +"y "); } }
  • 197. 197如果语句是一条语句就可以不用代码块,此时语句的格式就是下面的形式。 if( <表达式> ) 语句;例如,if (isMoving){ currentSpeed--; } 就可以改写成这样的形式: if (isMoving) currentSpeed--;
  • 198. 1982.if…else语句if语句的另一种形式是if…else…。它提供了一种当测试求得的值为false时程序执行的第二条路径。语法格式:if(<表达式>){ 语句1; }else{ 语句2; }在此语句中如果<表达式>的值为true(真),则执行该语句1,否则执行语句2。下面是if语句的执行流程图。
  • 199. 199199<表达式>语句1truefalse语句2if…else 语句执行流程图
  • 200. 200例如, if(flage==true && i>1){ n=getInitNumber(); m=1; }else{ n=getNextNumber(); m=0; }
  • 201. 201与if类似,如果语句是一条语句就可以不用代码块,此时语句的格式就是下面的形式。 if( <表达式> ) 语句1; else 语句2; 例如,if (isMoving){ currentSpeed--; }else{ currentSpeed++; } 就可以改写成这样的形式: if (isMoving) currentSpeed--; else currentSpeed++;
  • 202. 202例 ch03_6_2 从键盘输入两个double数分别存入变量x和y,判断它们之间的关系。如果x小于y就提示“x小于y”;如果x大于y就提示“x大于y或等于y”;如果x等于y就提示“x等于y”。(源程序: ch03_6_2.java)
  • 203. 203203import java.util.*; import java.io.*; public class ch03_6_2{ public static void main(String []argc){ Scanner sc = new Scanner(System.in); String msg; double x,y; System.out.print("Input frist Number:"); x = sc.nextDouble(); System.out.print("Input seconday Number:"); y = sc.nextDouble(); if(x > y){ msg = "大于"; }else{ if(x
  • 204. 2042043.if语句的嵌套if和if…else语句允许嵌套,用于处理一些复杂的选择关系。嵌套的一般形式如下:if(…){ …… if(…){ …… if(…){ …… } …… } …… } if(…){ …… if(…){ …… }else{ if(…){ …… }else{ …… } …… } …… }
  • 205. 205…… c=sc.getChar(); if(c<32) System.out.println("This is a control character"); else { if(c>='0'&&c<='9') System.out.println("This is a digit"); else if(c>='a'&&c<='z') System.out.println("This is a small letter"); else if(c>='A'&&c<='Z') System.out.println("This is a capital small letter"); else System.out.printf("This is an other character"); } ……考察下面的代码。
  • 206. 2062064.switch语句不像if - then和if-then-else,switch开关声明允许任何数量的可能的执行路径。语句的一般形式: switch(<表达式>){ case 常量1: 语句1; [break;] case常量2: 语句2; [break;] …… [default: 默认处理语句] }
  • 207. 207207switch语句根据表达式的值执行不同的代码,虽然多路选择结构可以用if-else-if….实现,但使用switch更好一些。 语句中的<表达式>可以返回一个简单类型,case语句指定的“常量”值的类型必须与之兼容,而且这个值必须是唯一的。switch语句的表达式可以使用: byte、short、char、int等原始数据类型。 枚举类型。 包含原始类型Character、 Byte、 Short、和 Integer 的一些类。 考察下面程序代码:
  • 208. 208208int month = 8; switch (month) { case 1: System.out.println(“一月"); break; case 2: System.out.println(“二月"); break; case 3: System.out.println(“三月"); break; case 4: System.out.println(“四月l"); break; case 5: System.out.println(“五月"); break; case 6: System.out.println(“六月"); break; case 7: System.out.println(“七月"); break; case 8: System.out.println(“八月"); break; case 9: System.out.println(“九"); break; case 10: System.out.println(“十月"); break; case 11: System.out.println(“十一月"); break; case 12: System.out.println(“十二月"); break; default: System.out.println(“错误月份额值");break; } 八月
  • 209. 209209switch语句执行流程图表达式常量1语句1常量2语句2常量n语句n语句
  • 210. 210210例 ch03_6_7有五中食物---鸡蛋、牛奶、西瓜、黄瓜、猪肉,分别与数字1-5相对应。从键盘输入1-5,显示对应食物。如果数字没有与之对应的食物则提示错误。源程序ch03_6_7.java
  • 211. 211211import java.io.*; import java.util.*; public class ch03_6_7 { public static void main(String args[]){ String strMsg[]={"鸡蛋","牛奶","西瓜","黄瓜","猪肉"}; Scanner sc = new Scanner(System.in); String strTxt=null; int code=0; System.out.print("输入数字1-5:"); code = sc.nextInt(); switch(code-1){ case 0: strTxt=strMsg[0]; break; case 1: strTxt=strMsg[1]; break;转 下 页
  • 212. 212212 case 2: strTxt=strMsg[2]; break; case 3: strTxt=strMsg[3]; break; case 4: strTxt=strMsg[4]; break; default: strTxt="输入的数字不对,请输入1-5."; } System.out.println(strTxt); } }接 上 页
  • 213. 213213第二章、Java语言基础基础语言 (循环语句和分支 )
  • 214. 2142142.7、循环和分支语句循环语句用于需要重复性数据处理或操作。Java提供了三种形式的重复操作语句: for语句。 while语句。 do-while。 分支语句控制流程跳过某些代码块,跳转到指定的语句处继续执行。Java提供了三种分支语句: break语句。 continue语句。 return语句。
  • 215. 2152151.for语句for(初始化;终止条件;增量){ 语句块; }for语句提供一种紧凑的途径迭代一个值范围。程序设计常把它归属与“for loop”,因为在这种方式重复循环直到指定的特定条件被满足。是比较常用的一种重复结构,语法格式:语句块。被迭代或重复执行的部分。
  • 216. 216初始化表达式。用于终止条件以及语句块中变量的初值设置。仅在循环开始时执行一次。 终止条件表达式。当终止条件表达式的计算结果为true(真)则继续循环;当计算结果为false(假)就结束循环。 增量表达式。每次迭代或重复到循环结尾时执行,就是当语句块被执行结束后执行它。用来改变终止条件表达式中相关变量的值。这个表达式可以是增量的,或者是减量的,如 ++ 或 --。下图反映for语句执行流程。
  • 217. 217初始化条件表达式语句(循环体)条件控制 假真for语句执行流程
  • 218. 218例如下列程序:class ForDemo { public static void main(String[] args){ for(int i=1; i<11; i++){ System.out.println("Count is: " + i); } } }Count is: 1 Count is: 2 Count is: 3 Count is: 4 Count is: 5 Count is: 6 Count is: 7 Count is: 8 Count is: 9 Count is: 10
  • 219. 219(1)for语句使用注意事项:初始化部分可以声明变量,声明的变量的有效范围是从声明开始到语句块结尾。通常,如果控制循环的变量不需要在 for的外面时,最好在初始化部分声明它。 初始化、终止条件和增量这三个表达式是可选的。在for语句中可省略,如果三个表达式全部省略,那么就是一个无限循环,例如 for( ; ; ){ …… } 就是无限循环。
  • 220. 220(2)增强格式的for语句:对于数组(Arrays)和集合(Collections)的迭代,有一种更紧凑易读的for语句形式。语法格式:for(元素型变量:数组型或集合型变量){ 语句; }元素型变量 与数组型或集合型变量元素类型相同的变量。 数组型或集合型变量 数组类型或集合类型的变量。
  • 221. 221例如下面的程序:class EnhancedForDemo { public static void main(String[] args){ int[] numbers = {1,2,3,4,5,6,7,8,9,10}; for (int item : numbers) { System.out.println("Count is: " + item); } } }Count is: 1 Count is: 2 Count is: 3 Count is: 4 Count is: 5 Count is: 6 Count is: 7 Count is: 8 Count is: 9 Count is: 10
  • 222. 222(3)示例:例 ch03_7_1 计算 1+2+3+…+100 的结果。public class ch03_7_1{ public static void main(String []argc){ int sum = 0; for(int i=1;i<=100;i++){ sum += i; } System.out.println("1+2+3+¡­+100="+sum); } }(源程序: ch03_7_1.java)
  • 223. 223例 ch03_7_2 计算 1×2×3×…×15 的结果。(源程序: ch03_7_2.java)public class ch03_7_2{ public static void main(String []argc){ long inv = 1; for(int i=1;i<=15;i++){ inv *= i; } System.out.println(" 1×2×3×…×15 ="+inv); } }
  • 224. 2242.while语句while语句频繁执行当指定条件为true的语句块,语法格式: while(表达式){ 语句(循环体); }其中、表达式的结果是一个boolean类型的值,如果为true循环体就可被执行;反之,则执行下一条语句。while执行流程图如下。
  • 225. 225225条件表达式语句(循环体)真假while循环执行流程
  • 226. 226例如, class WhileDemo { public static void main(String[] args){ int count = 1; while (count < 11) { System.out.println("Count is: " + count); count++; } } }
  • 227. 227例 ch03_7_4 计算 1+2+3+…+100 的结果。(源程序: ch03_7_4.java)public class ch03_7_4{ public static void main(String []argc){ int sum = 0,i = 1; while(i<=100){ sum += i; i++; } System.out.println("1+2+3+¡­+100="+sum); } }
  • 228. 228例 ch03_7_5 计算 1×2×3×…×15 的结果。(源程序: ch03_7_5.java)public class ch03_7_5{ public static void main(String []argc){ int i = 1; long inv = 1; while(i<=15){ inv *= i; i++; } System.out.println(" 1×2×3×…×15 ="+inv); } }
  • 229. 2292293.do…while语句do-while语句,与while类似,只不过把表达式放在了循环体的后面,语法格式:do{ 语句(循环体); }while(表达式);其中、表达式的结果是一个boolean类型的值,如果为true循环体就可被执行;反之,则执行下一条语句。与while不同的是do…while不论表达式是否为true语句都会执行一次。do…while执行流程图如下。
  • 230. 230条件表达式语句(循环体)do-while循环执行流程
  • 231. 231例如class DoWhileDemo { public static void main(String[] args){ int count = 1; do { System.out.println("Count is: " + count); count++; } while (count <= 11); } }
  • 232. 2322324.break 语句break语句有两种形式:带标签的和不带标签的,语法格式:break label(标签); break;不带标签的用在退出循环、终止switch的一种选择。当需要结束循环时最好依靠循环调件控制,尽量不要使用break语句强制结束循环。对于在循环体内部的switch选择,break语句仅对switch语句有效,不能终止循环的进行,
  • 233. 233233带标签的用于使程序跳转到标签标志的位置执行。标签是一个标识符,标签的格式: …… 标签:… 例如下面的程序段。search: for (i = 0; i < arrayOfInts.length; i++) { for (j = 0; j < arrayOfInts[i].length; j++) { if (arrayOfInts[i][j] == searchfor) { foundIt = true; break search; } } }
  • 234. 2342345.continue 语句continue语句有两种形式:带标签的和不带标签的,语法格式:continue label(标签); continue;不带标签的continue语句跳过for、while和do-while循环体的尾部,计算控制循环的条件表达式。 带标签的continue语句跳过当前迭代,跳转到循环外面的标签处执行。标签是一个标识符,标签的格式: 标签:… 例如下面的程序段。
  • 235. 235…… test: for (int i = 0; i <= max; i++) { int n = substring.length(); int j = i; int k = 0; while (n-- != 0) { if (searchMe.charAt(j++) != substring.charAt(k++)) { continue test; } } foundIt = true; break test; } ……
  • 236. 2362366.return 语句return语句结束当前方法,控制流程返回到调用它的方法。return 语句有两种形式:带有一个返回值的和不带返回值的。语法格式:return 表达式; return;return 表达式。计算并返回表达式的值,结束当前方法。 return;。结束当前方法。
  • 237. 237237例如下面程序段。 …… public void calcuArea(){ …… area = getArea(); …… } …… public int getArea() { …… return width * height; }
  • 238. 238238第二章、Java语言基础基础语言 (数组)
  • 239. 2392392.8、数组数组是常用的数据结构,由数据类型相同的元素按一定顺序线性排列构成。它是一个容器对象,拥有有固定数量的单一类型的值。当数组创建后数组的长度就确定了,就是说数组创建后长度就是固定的。数组有如下的特点: 数组是相同数据类型元素的集合。 数组中元素有先后顺序。 数组的元素用它自己的位置和数组名称表示。 数组只能动态创建。 对于数组需要了解一些概念或术语。这些术语主要有:元素,下标和长度。
  • 240. 240元素 数组中的每个数据项称作“元素”。元素的数据类型都相同。 下标 用于访问每项的数字索引号。下标从0开始,到数组长度-1。 长度(数组元素数) 数组中包含的元素数目。数组类型提供 length 记录数组的长度。如图所示的数组,数组元素数为10,下标从0开始,到9结束。
  • 241. 241
  • 242. 2422421.一维数组所谓一维数组指每个元素由一个下标唯一确定数组。 数组类型 数组名称; 或 类型[] 名称; (1)声明一维数组一维数组的声明语法格式:例如 int[] anArray; String[] agrs;
  • 243. 243数组名称 可以是任何符合标识符命名规则的符号串。数组类型 由类型和[]组成,即写成 类型 []。类型是所包含的元素的数据类型,可以使用原始数据类型和其他引用型数据类型。 []表明变量为数组。注意数组的尺寸不是数组类型的组成部分。 数组类型也属于引用型数据类型。声明数组不代表着实际创建一个数组,仅仅简单地告诉编译器变量拥有指定类型的数组。要使数组实际存在还必须 创建数组。声明的数组型变量是引用型变量。
  • 244. 244例如,下面声明几个不同类型的数组。int[] iArray; float[] fArray; char[] cName; double[] dChart; Applet[] aAppletSet; Object[] oOb; Array[] aArrayList; Boolean[] bFlags; Thread[] tRunning;
  • 245. 245(2)创建一维数组声明的数组型变量是引用型变量,因此数组声明后只有通过创建才能够使用。创建数组要使用new运算符实现。创建数组通过两个途径: 数组声明后用new运算符创建,语法格式: 数组变量 = new 类型[长度]; 数组声明时用new运算符创建,语法格式: 类型[] 数组变量 = new 类型[长度]; 如果数组没用创建就直接使用,编译器会提示编译错误:Variable Xxxx may not have been initialized. 数组变量 = new 类型[长度];类型[] 数组变量 = new 类型[长度];
  • 246. 246例如 int[] aArray; aArray = new int[100]; float[] fArray; fArray = new float[35]; double[] dData = new double[23]; String[] sTitle = new String[15];
  • 247. 247(3)使用一维数组数组的每个数组元素通过数组的数字索引即下标访问,其语法格式: 名称[下标] 例如 int[] iNode = new int[4]; iNode[0] = 1000; iNode[1] = iNode[0] + 1; iNode[2] = iNode[1] + 2; iNode[3] = iNode[2] + 3;名称[下标]
  • 248. 248(4)初始化一维数组数组创建后需要为数组的每个原始赋值,这个过程称作初始化数组。初始化数组有两个途径: 通过赋值语句为每个元素分配值,其语法格式: 名称[下标] = <表达式>; 例如 int[] iCode = new int[4]; iCode[0] = 2000; iCode[1] = 2001; iCode[2] = 2002; iCode[3] = 2003;名称[下标] = <表达式>;
  • 249. 249声明数组的同时创建并初始化数组,其语法格式: 类型[] 名称 = {元素1,元素2,…}; 此时,数组的长度由包含在{……}之间的元素数目决定。例如 int[] iCode = {2000, 2001, 2002, 2003}; 元素的数目是4,即数组的长度是4. int[] anArray = {100,200,300,400,500,600,700}; 元素的数目是7,即数组的长度是7.类型[] 名称 = {元素1,元素2,…};
  • 250. 250(5)复制数组在System类中arraycopy 方法用来复制数组给另外一个数组:public static void arraycopy( Object src, //源数组 int srcPos, //源数组中的起始位置 Object dest,//目标数组 int destPos,//目标数据中的起始位置 int length //要复制的数组元素的数量 )
  • 251. 251例 ch03_8_1 生成30个随机double数,数值:0.1~9.0之间。将这30个数存放到数组 dRandom。(源程序:ch03_8_1.java)分析: 随机数可用Math类的random()方法生成。这个方法生成0.0~1.0之间随机double类型的浮点数。 创建一个名为dRandom的数组,存放格生成的随机数。 (6)一维数组示例
  • 252. 252例 ch03_8_1执行结果
  • 253. 253public class ch03_8_1{ public static void main(String []argc){ double[] dRandom; int I = 0; dRandom = new double[30]; while(i<30){ dRandom[i] = 9.0*Math.random(); System.out.println("dRandom["+i+"]="+dRandom[i]); i++; } } }
  • 254. 254例 ch03_8_2 随机产生100个300~9000之间的整数,然后从大到小排序。(源程序:ch03_8_2.java)分析: 随机数可用Math类的random()方法生成。这个方法生成0.0~1.0之间随机double类型的浮点数,因此需要乘以9000,并强制转换为int类型。 创建一个int类型的数组,存放格生成的随机数。 排序有多种方法,这里使用简单的相邻两个数之间比较方法。
  • 255. 255主要程序段:<1> 生成100个在300~9000之间的整数 while(i<100){ iNum = (int)(9000*Math.random()); if(iNum>=300 && iNum<=9000){ iData[i] = iNum; i++; }else continue; }
  • 256. 256<2> 排序(从大到小排序) for(int j=0;jiData[i]){ iNum = iData[i]; iData[i] = iData[j]; iData[j] = iNum; } } }
  • 257. 2572.二维数组所谓二维数组指每个元素由两个下标唯一确定数组。就是所谓的数组的数组(an array of arrays )。 数组类型 数组名称; 或 类型[][] 名称; (1)声明二维数组二维数组的声明语法格式:例如 int[][] anArray; String[][] agrs;
  • 258. 258258数组类型 由类型和[][]组成,即写成 类型 [][]。 类型是所包含的元素的数据类型,可以使用原始数据类型和其他引用型数据类型。 [][]是表明变量为数组的特征符号。注意数组的尺寸不是数组类型的组成部分。 数组类型也属于引用型数据类型。 在二维数组中,第一个下标又称作行号;第二个下标称作列号。
  • 259. 259数组名称 可以是任何符合标识符命名规则的符号串。声明数组不代表着实际创建一个数组,仅仅简单地告诉编译器变量拥有指定类型的数组。要使数组实际存在还必须 创建数组。声明的数组型变量是引用型变量。
  • 260. 260(2)创建二维数组声明的数组型变量是引用型变量,因此数组声明后只有通过创建才能够使用。创建数组要使用new运算符实现。创建数组通过两个途径: 数组声明后用new运算符创建,语法格式: 数组变量 = new 类型[行数][列数]; 数组声明时用new运算符创建,语法格式: 类型[][] 数组变量 = new 类型[行数][列数];数组变量 = new 类型[行数][列数];类型[][] 数组变量 = new 类型[行数][列数];
  • 261. 261例如,int[][] iMoving; iMoving = new int[5][6]; float[][] fHeight; fHeight = new float[2][8]; long[][] lDes = new long[4][4]; double[][] dFly = new double[10][5];
  • 262. 262(3)使用二维数组数组的每个数组元素通过数组的数字索引即下标访问,其语法格式: 名称[下标] 例如 int[][] iNode = new int[4][2]; iNode[0][0] = 1000; iNode[0][1] = iNode[0][0] + 1; iNode[1][0] = iNode[0][1] + 2; iNode[1][1] = iNode[1][0] + 3; ……名称[行下标][列下标]
  • 263. 263263(4)初始化二维数组数组创建后需要为数组的每个原始赋值,这个过程称作初始化数组。初始化数组有两个途径: 通过赋值语句为每个元素分配值,其语法格式: 名称[下标] = <表达式>; 例如 int[][] iCode = new int[2][2]; iCode[0][0] = 2000; iCode[0][1] = 2001; iCode[1][0] = 2002; iCode[1][1] = 2003;名称[行下标][列下标] = <表达式>;
  • 264. 264声明数组的同时创建并初始化数组,其语法格式: 类型[][] 名称 = {{元素1,元素2,…},…}; 此时,数组的长度由包含在{……}之间的元素数目决定。Java语言允许第二维有不同的元素数,即可以不是等长度的。 例如 int[][] iCode = {{2000,2001},{2002,2003}}; int[][] anA = {{100,200},{300,400},{500,600}}; int[][] iData = {{1,2,3,4},{5,6,7,8},{9,10}};类型[][] 名称 = {{元素1,元素2,…},…};
  • 265. 265(5)二维数组的特点在Java语言里,二维数组实际上是数组的数组,即第一维元素是指向同类型数组的引用。 一个二维数组型变量其实是一个含有若干一维数组型变量的引用。 第一维每个元素对应的一维数组的长度可以不相同。
  • 266. 266(6)二维数组示例例 ch03_8_5 将矩阵 转换成: (源程序:ch03_8_5.java)1 2 3 4 5 6 7 81 5 2 6 3 7 4 8
  • 267. 267public class ch03_8_5{ public static void main(String []argc){ int[][] iData = {{1,2,3,4},{5,6,7,8}}; int[][] iNew = new int[4][2]; for(int i=0;i<2;i++){ for(int j=0;j<4;j++){ System.out.print(" "+iData[i][j]); iNew[j][i] = iData[i][j]; } System.out.println(" "); } 转 下 页
  • 268. 268268 for(int i=0;i<4;i++){ for(int j=0;j<2;j++){ System.out.print(" "+iNew[i][j]); } System.out.println(" "); } } } 接 上 页
  • 269. 269269第二章、Java语言基础基础语言 (应用示例)
  • 270. 2702702.9、应用示例 设定两个整数m和n,计算它们的最大公约数和最小倍数。 打印“魔方阵”。 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
  • 271. 271271示例 1.设定两个整数m和n,计算它们的最大公约数和最小倍数。(1)题解最大公约数指两个整数共同拥有的最大约数。例如48和36的最大公约数是 12。 最小公倍数指两个整数共同拥有的最小倍数。例如48和36的最小公倍数是144。 程序要求在给定两个整数后,计算出这两个数的最大约数和最小倍数。(源程序:ch03_9_1.java)
  • 272. 272(2)实现两个整数分别由定义的两个int或long类型的变量表示,变量名称分别是 m 和 n(也可以用别的名称)。 m和n的值,可以直接用在程序中给定的常量,或者从键盘输入。如果从键盘输入,使用Scanner类提供的方法nextInt()从键盘接收数据。 计算最大公约数和最小公倍数用两个独立的程序分别实现,即方法maxCommDiv和maxCommMul。(有关方法的概念在后面章节介绍) Java程序是以类或对象为单元的,所以该程序必须是一个类,并且类名和程序源文件名相同,这里类名称用ch03_9_1,源文件名为ch03_9_1.java。
  • 273. 273(3)算法流程定义变量m,n, maxDiv,maxMul开始输入整数给m和n计算最大公约数 maxDiv计算最小公倍数 maxMul显示计算结果开始主程序流程
  • 274. 274最大公约数计算流程定义变量maxm
  • 275. 275最小公倍数计算流程定义变量maxm>nm→maxn→maxmax/m或max/n 余数为0吗?max +1→max返回maxYYNN
  • 276. 276(4)程序解释public static int maxCommDiv(int m,int n){ int commDiv; if(m
  • 277. 277变量commDiv用来表示最大公约数。它的初值设置成两个整数中比较小的整数的值。 int commDiv; if(m
  • 278. 278用commDiv分别除以两个整数,检查它们的余数是否都为0。 如果不为0,就将commDiv的值减一,继续比较它们的余数是否都为0,即重复a)。 如果余数为0,说明当前commDiv变量的值可以同时整除两个变量。在这里commDiv是它们的公约数。while(m%commDiv!=0 || n%commDiv!=0){ commDiv--; }
  • 279. 279public static int maxCommMul(int m,int n){ int commMul; if(m>n) commMul = m; else commMul = n; while(commMul%m!=0 || commMul%n!=0){ commMul++; } return commMul; }maxCommMul()方法计算两个整数的最小公倍数。
  • 280. 280变量commMul用来表示最小公倍数。它的初值设置成两个整数中比较大的整数的值。 int commMul; if(m>n) commMul = m; else commMul = n;
  • 281. 281使commMul分别被两个整数除,检查它们的余数是否都为0。 如果不为0,就将commMul的值加一,继续比较它们的余数是否都为0,即重复a)。 如果余数为0,说明当前commMul变量的值可以同时被两个变量整除。在这里commMul是它们的公倍数。while(commMul%m!=0 || commMul%n!=0){ commMul++; }
  • 282. 282程序运行结果
  • 283. 283示例 2. 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9(源程序:ch03_9_2.java)打印“魔方阵”,如下图所示。
  • 284. 284(1)题解题目的关键问题是如何构造“魔方阵”?通常的实现方法是: 将1放在第一行的中间位置。 从2开始到25(即52),计算和放置数字规则: 如果上一个数字的右上方为空,当前数字放在上一个数的右上方。 否则放在上一个数的正下方。
  • 285. 285(2)实现从这个“阵”的图形可以看出,它由5行5列数字构成的网格。显然使用一个5x5的二维数组存放网格中的数字是比较好的解决方案。因此定义一个数组型变量 m 来满足题目的要求。 计算网格中每个数字,用嵌套的循环语句结构来实现。 显示“魔方阵”同样用嵌套的循环语句分别按行、列显示数组中的每个数字。
  • 286. 286(3)程序解释public static final int N = 5; 定义常量N表示二维数组的行数和列数。int[][] m = new int[N][N];声明int[][] 数组型变量 m ,并创建含有5行5列的二维数组。
  • 287. 287i = 0; j = N/2;;m[i][j] = 1;设置计算开始时,数组的初始行列下标值,即第一行中间列的下标。将1放置在第一行中间列。
  • 288. 288for(number = 2;number<=N*N;number++){ if(m[(i-1+N)%N][(j+1)%N]==0){ i=(i-1+N)%N; j=(j+1)%N; }else{ i=(i+1)%N; } m[i][j]=number; }放置2~25之间的数字。判断右上方是否为空(即0)。为空,计算右上方位置。不为空,计算正上方位置。填写数字。
  • 289. 289程序运行结果
  • 290. 290290第三章、抽象、封装与类类与对象 (抽象与封装)
  • 291. 2912913.1、抽象与封装抽象和封装是面向对象程序设计的重要特征。 抽象意味着忽略事物的某些差异而抽取其共同特征。一个软件构件也有相同的原则。 封装原则把对象的属性和操作结合为一个完整的实体,屏蔽了对象的内部实现细节,对外呈现一定的接口,这使得对象具有了独立性和完整性,从而具备了可复用构件的基本特性。
  • 292. 2921.抽象所谓抽象,就是除去研究对象中与主题无关的次要部分或暂不考虑的部分,而仅仅抽取与研究有关的实质性内容加以考察。计算机软件开发中所用到的抽象有两类:过程抽象和数据抽象。即舍弃个别的功能,抽取共同拥有的功能。在抽象过程中,将整个系统划的功能分成若干部分,强调功能完成的过程和步骤。 基于过程的程序设计方法通常采用这种抽象。(1)过程抽象
  • 293. 293示例 有100个实验数据,从键盘输这100它们,然后按从小到大的顺序排序,并输出重新排序后的结果。 分析: 按任务目标,要输出排序后的数据。处理过程可归纳成三个主要过程,即数据输入、排序和输出。这三个主要过程实际就是数据处理程序的三个功能,三个功能按顺序完成,就可以达到任务所要求的目标。那么程序可以抽象成如下四个部分(见下图): 主程序 输入程序 排序程序 输出程序
  • 294. 294主程序输入排序输出功能树图 功能树图
  • 295. 295 实现(C语言程序)void main() { int data[120]; input(data); sort(data); display(data); }void input(int *pData) { …… } void sort(int *pData) { …… } void display(int *pData) { …… }说明: 因为Java语言无法实现过程抽象,因此这里采用C语言,仅为说明概念只用。
  • 296. 296所谓数据抽象,把整个系统中需要处理的数据和与数据相关的操作结合在一起,根据功能、性质、作用等因素抽象成不同的数据类型,包括针对数据授权的操作。是相对过程抽象更为严格,更为合理的抽象方法。面向对象软件开发方法采用的就是这种抽象方法。 在面向对象程序设计方法中的面向对象的分析,就是对实际问题抽象,从而建立物理模型,生成抽象数据类型的过程。(2)数据抽象什么是数据抽象
  • 297. 297数据抽象一般过程面向对象问题求解实际上就是从实际问题中寻找和发现对象,本质上就是如何从实际问题抽象出封装了数据和操作的对象。 对象是现实世界中的实体或概念在计算机逻辑中的抽象表示,具有唯一名称和对外固定接口的一组属性和操作的集合,用来模拟组成或影响现实问题的一个或一组因素。 具有相同特征的对象可以抽象成一种新的数据类型——类,来描述这些对象的共同属性和特点。下图表示现实世界对实体的概念抽与计算机对对象抽象描述的对应关系
  • 298. 298计算机世界实体对象类创建现实世界概念世界抽象类抽象定义类对应现实世界对实体的概念抽与计算机对对象抽象描述的对应关系
  • 299. 299示例 有100个实验数据,从键盘输这100它们,然后按从小到大的顺序排序,并输出重新排序后的结果。 分析: 按任务目标,要输出排序后的数据。这里排序是主要任务,可以把与排序相关的抽象出来,认为“排序”是一个实体或者对象。它具有如下的特征: 它包含一组数据。 对数据按从小到大重新排列。 显示所包含的数据(排序后)。
  • 300. 300 排序类型(Sort Type)数据1(排序前) 数据2(排序后)初始化 排序 显示 …… 属性操作
  • 301. 301 实现(Java语言程序)public class SortType{ int []data1; int []data2; public SortType(int []data){ …… } public void input(int []data){ …… } public void sort(){ …… } public void display(){ …… } }
  • 302. 302所谓封装,即利用抽象数据类型将数据和基于数据的操作捆绑封装在一起,数据被保护在抽象数据类型的内部,必须通过包裹在数据外层的被授权的操作才能访问这个抽象数据类型的内部数据。 封装的重点是对数据的封装,因此上将隐藏内部状态,请求的所有相互作用通过对象方法实现称作“数据封装”。2.封装什么是封装
  • 303. 303封装的优点封装对于软件开发提供的益处有两个主要方面: 模块性: 对象的源代码可以被独立于其他对象的源代码来编写和维护。同样,对象可以被容易地在系统内分发。 信息隐藏: 对象有一个公共接口,其他对象使用它与这个对象通讯。对象可以提供私有信息和方法,它们可以在任何时间被改变而不会影响其他依赖它的对象。
  • 304. 304封装的内涵封装是将对象的属性和行为分别用数据结构和方法描述,并将它们绑定在一起形成一个可供访问的基本逻辑单元。也就是将数据和操作封装在一起,成为一个不可分隔的整体。如下图:属性或数据 (状态)操作或方法 (行为)
  • 305. 305封装的表达面向对象程序设计中,抽象数据类型使用“类”表示的,“类”是一种可以被面向对象工具可理解和可操纵的结构。“类”封装了所抽象的抽象数据类型的相关数据和操作。类的构成如下图所示:
  • 306. 306306第三章、抽象、封装与类类与对象 (声明Java类)
  • 307. 3073073.2、声明Java类1.类与对象(1)对象 对象是相关域和方法的复合体。对象通常用来模拟现实世界中的真实对象,是模拟包含许多状态和行为的现实世界对象的模型。一个软件对象包含状态和相关的行为。 对象用一个或多个“域(fields)”存储它的状态。 通过“方法(methods)”表达它的相关联的行为。方法操作对象的内部状态,并充当对象与对象之间通讯的主要途径。 在对象中,状态和行为被封装成一个整体,从而对外界隐藏了自己。
  • 308. 308对象是域与相关方法捆绑在一起的软件。下图表示一个软件对象: 扇形区域表示对象的方法,中间圆形区域表示数据区域。 对象的核心是数据,方法提供与数据相关的操作或处理。域方法
  • 309. 309 域 对象的状态存储在“域”,有时又被称做变量。这些变量形式上称为实例变量(instance variables),因为他们包含具体的对象的状态,在面向对象术语中,一个具体对象被称为一个实例。实例变量(instance variable): 与具体对象关联的所有数据项。每个类的实例有它自己拥有的定义在类中的实例变量的拷贝,又被称作“域”。
  • 310. 310 方法 对象的行为通过“方法”体现出来,方法又被称做函数。方法: 操作对象内部的状态。 充当对象-对象间的通讯机制。 为隐藏的内部状态,通过对象方法实现所有的交互请求。实例方法(instance method) : 所有被相关类实例调用的方法,也简单地称为“方法”。
  • 311. 311捆绑代码在单独的软件对象中提供了一些好处,包括: 模块化: 对象源代码编写和维护独立于其他对象的源代码。一旦创建,对象可以容易地被分发到其他的系统。 信息隐藏: 相互作用通过对象的方法,内部实现的细节对外部世界隐藏。 代码重用: 如果对象已经存在,你可以在你的程序中使用这个对象。
  • 312. 312 可插入性: 如果特定的对象原来是有问题的,你可以简单地从应用程序中移去它,并插入一个其他的不同对象做为替代。
  • 313. 313(2)类 在真实世界中,许多有相同种类的特定对象,它们都有相同的构造和模型。每个真实对象都来源于相同的设计图,而且包含相同的部件。用面向对象术语,对象是类的一个实例,类是被创建对象的设计图。类 :创建的对象的设计图(blueprint)或原型(prototype )。 对象:类的一个实例(instance )。面向对象软件中也有许多相同种类的对象,它们也有共同的特性,这些相同类型的对象是相似的,而且象创建于一个描述它们相同的特性蓝图,这种软件的蓝图可以被称做“类”,下图是对类的直观表示。
  • 314. 314类的直观表示 域 (表示状态)方法 (表示行为)
  • 315. 315 类(class): 定义特定类型的所有对象的共同域和方法的一个蓝图。 具有相同特征的对象可以抽象成一种新的数据类型——类,来描述这些对象的共同属性和特点。 类是对象特征的描述,通过类确定对象如何创建、对象包含的数据和方法。在Java程序设计语言中,一个类型定义对象类别细节的实现。一个类定义定义实例以及类变量和方法,指定类实现和类的直接超类的接口。如果超类没有明确被指定,那么隐含的超类将是Object类。
  • 316. 316通过类创建的对象称为类的“实例”。 实例变量(instance variable):与具体对象关联的所有数据项。每个类的实例有它自己拥有的定义在类中的实例变量的拷贝,又被称作“域”。 实例方法(instance method) :所有被相关类实例调用的方法,也简单地称为“方法”。 类的实例(instance):在用Java写的程序中,一个类的实例是用new操作符通过跟随在后的类名称创建,即: 实例 = new 类名称;
  • 317. 3172.声明Java类类是Java的核心,在Java看来“一切事物都是类”。定义类实际是确定它确切形式和属性,通过指定类所包含的数据和对数据进行操作的代码来实现。 { 域; 方法声明; …… }(1)声明类的格式[修饰符] class 类名称 [extends 父类]类体部类头部
  • 318. 318修饰符 修饰符决定着类在程序运行中被处理的方式,控制着变量或对象的可访问性。可以使用默认的修饰符,也可以显式指定。这里主要有三种修饰符: public(共有的) 可以被其他任何类使用,如果没有这个修饰符类只能被与它在同一个包中的其他类使用。 final(最终的) 被它修饰的类不能产生子类。 abstract(抽象的) 不能被实例化。
  • 319. 319class 说明这是类声明,类的名称为class后面的“类名称”。 extends 关键字extends子句,声明类的父类。是可选的,如果没有明确指出“父类名称”,那么隐含地父类是Object。在Java类声明中,父类只能有一个。 包含在“{…}”之间的部分为类的体部,提供类的具体内容,包括:域,构造方法,声明方法等。下图显示一个类的结构。
  • 320. 320
  • 321. 321(2)Java类的组成一般来说,类声明可能包括这些组件,依次是:修饰(Modifiers ) 类声明使用顶级访问控制符:public和package-private ,也可使用final和abstract。 类名称(class name) 按惯例,名称的初始字母大写。 父类名称(parent class) 接口列表(interface name) 类体部(class body)
  • 322. 322public class car extends motorcar { String name; int seating; public car(){ } public boolean isRun(){ } }例声明名称为car的类,它的父类是motorcar。因为它被public修饰,所以它可以被其他类使用。这个类的体部包括四个成员,两个数据成员name和seating,两个方法成员car和isRun。
  • 323. 323例用Java类表示解析几何学坐标系上的点,设点的坐标p(x,y)。(源程序文件:Point.java) 分析在平面解析几何中,点为基本的几何图形,图形的位置由点确定。所以可以将它抽象成一种数据类型,描述在坐标系上的点或其它几何图形的位置。 根据平面解析几何的定义,平面坐标系上的点有横坐标值和纵坐标值,即 x坐标和y坐标。因此用ox,oy两个变量表示它们。 做为数据类型需要有一个类型名称,在此例中命名为Point。
  • 324. 324public class Point{ private double ox,oy; public Point(){ } public Point(double x,double y){ ox = x; oy = y; } public double getX(){ return ox; }转 下 页 Java实现(源程序文件:Point.java)
  • 325. 325 public double getY(){ return oy; } public void setX(double x){ ox = x; } public void setY(double y){ oy = y; } }接 上 页
  • 326. 326程序也可分成两大部分: 类声明头部,即 public class Point。 public 修饰符。 class 关键字,表示声明类。 Point 类名称。 类体部,即{……}之间的内容,是类的实体部分,包含由类的属性和方法。
  • 327. 327例用Java类表示解析几何学圆形,设圆半径radius,圆心坐标p(x,y)。(源程序文件:Circle.java) 分析在解析平面几何中,圆形是基本的几何图形,同样把它抽象成一种数据类型,即圆类型,用Circle做为类型名称 。 圆需要三个数据项表示在平面坐标上的位置和范围,即圆心的坐标,用变量ox和oy表示,半径用radius变量表示。
  • 328. 328public class Circle{ private double radius; private double ox,oy; public Circle(){ } public Circle(double x, double y,double r){ ox = x; oy = y; radius = r; }转 下 页 Java实现(源程序文件:Circle.java)
  • 329. 329 public double getX(){ return ox; } public double getY(){ return oy; } public double getRadius(){ return radius; } }接 上 页
  • 330. 330程序也可分成两大部分: 类声明头部,即 public class Circle 。 public 修饰符。 class 关键字,表示声明类。 Circle 类名称。 类体部,即{……}之间的内容,是类的实体部分,包含由类的属性和方法。
  • 331. 3313.类成员访问控制访问级别修饰决定其他类是否可以使用特定的域或调用特定的方法。Java提供两个级别的访问控制: 顶级:public, or package-private (非显示修饰)。 成员级:public, private, protected, or package-private (非显示修饰)。(1)类声明可以用修饰public,在这种情况下,类在任何地方都是可见的。如果没有修饰,类仅在它自己所在的包中可见。
  • 332. 332(2)成员级控制,使用修饰public或没有修饰,如同顶级类一样,用同样的含义。对于成员有两个附加的控制修饰:private 和 protected。private 修饰的特定成员仅可被拥有它的类访问。protected 修饰的特定成员仅可悲拥有它的包以及在其它包的子类访问。(3)访问级别ModifierClassPackageSubclassWorldpublicYYYYprotectedYYYNno modifierYYNNprivateYNNN
  • 333. 3334.this在实例方法或构造器中,this是一个当前对象的引用——即正 在被方法或构造器调用的对象。可以使用this引用当前对象的任何成员。(1)用this引用域使用this的多数原因是因为一个域被方法或构造器的参数屏蔽,即参数名与域名相同。例如下面的代码:public class Point { public int x = 0, y = 0; public Point(int x, int y) { this.x = x; this.y = y; } }
  • 334. 334(2)用this引用构造器从一个构造器的内部,可以用this关键字调用在相同类中的另一个构造器。例如下面的程序:public class Rectangle { private int x, y,width, height; public Rectangle() { this(0, 0, 0, 0); } public Rectangle(int width, int height) { this(0, 0, width, height); } public Rectangle(int x, int y, int width, int height) { …… } }
  • 335. 335335第三章、抽象、封装与类类与对象 (声明成员变量)
  • 336. 3363363.3、声明成员变量1.成员变量声明格式在Java语言中有如下几种变量: 在类中的成员变量,又称域。 在方法或代码块中的局部变量。 在方法声明中的变量,又称参数。 域或成员变量声明包括三部分,按顺序: 0个或多个修饰符。 域类型。 域名称。
  • 337. 337修饰 类型 变量(域)名称;域或成员变量声明一般语法形式:例如下面的类中包括5个成员变量。class MemberVar { public int cup; private boolean win; protected String ballName; …… }
  • 338. 3382.访问修饰(Access Modifiers )修饰符用于控制其他类或对象使用域,决定其他类是否可以使用特定的域或调用特定的方法。对于类成员的访问控制,有两级控制: 在顶级,是public 或package-private (包私有,即无明确的修饰符)。 在成员级,public, private, protected, or package-private (包私有,即无明确的修饰符) 。 成员变量可以使用这两级访问修饰,控制成员变量的使用。
  • 339. 339public(共有的)域可以被所有类或对象访问。 被 public 修饰的成员变量,对于其他所有的类或对象都是可见的,可以被其他类或对象访问。考察下面的例子:public class PublicLevel{ public static int MAN=1; public static int WOMAN = 0; public int iSex; public String sYourName; }源程序: PublicLevel.java
  • 340. 340public class TestPublicLevel{ public static void main(String []argc){ PublicLevel pl1; pl1 = new PublicLevel(); pl1.iSex = PublicLevel.MAN; pl1.sYourName = "Tester One"; System.out.println("pl1.sYourName :" + pl1.sYourName); System.out.println("pl1.iSex :" + pl1.iSex); } }源程序: TestPublicLevel.java
  • 341. 341package-private(包私有,即无明确的修饰符)域可以被同一个包中的所有类或对象访问。 包私有,即在域或成员变量声明时没有指定修饰,例如下面的例子:public class PackagPrivateLevel{ int width,height; double area,ave; …… }
  • 342. 342protected(保护的)域可被拥有它的包以及在其它包的子类和子类的对象访问,例如下面的例子:public class Protected Level{ protected int width,height; protected double area,ave; …… }有关protected的详细解释和用法在类继承部分介绍。
  • 343. 343private(私有的)域仅能被拥有该域的类访问。 被 private 修饰的域,仅能在拥有它的类或对象中直接访问。其他类或对象不能直接使用这种域,例如下面的例子:public class PrivateLevel{ private String streetName; private int streetCode; …… }
  • 344. 344根据数据封装的原则,域通常用 private 修饰,这意味着它仅能被拥有它的类或对象直接访问。如果需要其它类使用域的值,可以用 public 方法提供对域的访问。public class PrivateLevel{ private String streetName; private int streetCode; …… public String getStreetName(){ return streetName; } public void setStreetName(String name){ streetName = name; } }
  • 345. 3453.类型(Type)类型,指域或成员变量的数据类型。所有变量必须有一个指定的类型。可以使用Java语言提供的任何数据类型: 原始类型,例如boolean、byte、char、short、int、long、float、double。 引用类型,String、Object等和其它类和接口。
  • 346. 3464.域(变量)名称域或成员变量的名称必须符合Java标识符的命名规则。在Java语言中对域的名称会按照这样的惯例命名: 名称的开始字符使用字母,而不用“_”和“$”。 后续字符可以是字母、数字和“_”。变量名称使用完整的单词,而非含义模糊的缩写。但按惯例也不使用“_”字符。 如果名称是一个单词,用小写。如果由多个单词组成,后续单词的第一个字母大写,例如currentDate、firstYear等。如果变量存储的值不改变的常量,用final修饰并名称用大写。
  • 347. 3475.初始化域大多数情况下需要给域提供一个初始值,即所谓的初始化。Java语言提供的初始化多种初始化方式。在声明变量的同时赋值,其语法格式: [修饰符] 类型 变量(域)名称 = <初始值>; 例如,private int number = 100; protected long length = 2300;(1)声明变量时同时赋值[修饰符] 类型 域或变量名称 = <初始值>;
  • 348. 348这种初始化形式的好处与不足: 当初始值有效并可以被写在一行时,这种形式效果很好。 但当初始化具有逻辑性,比如处理异常,循环填充队列或复杂数据结构,这种简单赋值就显得不适当。(2)在构造方法初始化实例变量实例变量可以在构造器中初始化,异常处理和其他有逻辑性的处理可在此完成。同常有两种选择在构造器中初始化实例变量:初始化代码块和final方法。
  • 349. 349实例变量初始化代码块的格式如下: { 初始化代码; } Java编译器会复制这个代码块到每个构造方法,因此这个初始化方法可用在多构造方法之间功享初始化代码块。考察下面的代码:初始化代码块(2)在构造方法初始化实例变量实例变量可以在构造器中初始化,异常处理和其他有逻辑性的处理可在此完成。同常有两种选择在构造器中初始化实例变量:初始化代码块和final方法。{ 初始化代码; }
  • 350. 350例 ch04_3_1 (源程序: ch04_3_1.java)public class ch04_3_1{ private int []number; static long count = 0; { number = new int[200]; for(int i=0;i
  • 351. 351 public ch04_3_1(){ } public ch04_3_1(int n){ } public ch04_3_1(int n,int m){ } public static void main(String []argc){ new ch04_3_1(); new ch04_3_1(1000); new ch04_3_1(2000,4300); } }接 上 页
  • 352. 352用final方法初始化对域的初始化还可以用final方法实现。用final方法初始化域的实现代码形式如下:private 变量类型 变量名称 = final方法名(); …… protected final 变量类型 final方法名() { //初始化代码 } ……程序ch04_3_2.java演示用final方法初始化域。
  • 353. 353 public class ch04_3_2{ private int []number = initNumber(); public ch04_3_2(){ } protected final int [] initNumber(){ int[] num = new int[200]; for(int i=0;i
  • 354. 3546.静态域用static修饰的域称为静态域,又称为“类变量”。用法格式:访问修饰 static 数据类型 变量名称;访问修饰包括:public、private、protected等。例如下面的代码:class PhoneCard{ static String connectNumber=“200”; static double cardNumber; …… }
  • 355. 355(1)静态域或类变量的特点不管类被实例化多少次(也就是创建多少个对象),类变量仅有一个,即类的多个实例(对象)共享类变量,是一个公共的存储单元。 类变量可以通过类名直接引用,例如Math.PI。(2)静态域初始化静态域初始化与非静态域类似的几种形式:可以在声明静态域时通过赋值初始化;代码块中初始化;在静态的final方法初始化(不能使用非静态)。下面的例子ch04_3_3.java演示上述静态域初始化过程。
  • 356. 356public class ch04_3_3{ private static int []m; private static int []n = initN(); private static int size = 4500; { m = new int[100]; System.out.println("非静态代码块执行."); } //默认构造方法 public ch04_3_3(){ }例 ch04_3_3 (源程序: ch04_3_3.java)转 下 页
  • 357. 357 // n初始化方法 protected static final int [] initN(){ int[] num = new int[200]; for(int i=0;i
  • 358. 358{ m = new int[100]; System.out.println("非静态代码块执行."); }protected static final int [] initN(){ …… }
  • 359. 359静态域初始化代码块(static initialization block )静态变量初始化代码块的格式如下: static{ 初始化代码; } 类中允许有多个这种静态初始化代码块,它们可以放置在类体部的任何地方。 当所在的类加载时由系统执行。运行系统保证按照它们在源程序中出现的顺序调用它们。 例子ch04_3_4.java演示上述静态域初始化代码块的使用。 static { 初始化代码; }
  • 360. 360例 ch04_3_4 (源程序: ch04_3_4.java)public class ch04_3_4{ private static int []m; private static int size = 4500; //静态初始化代码块1 static{ m = new int[100]; System.out.println("静态代码块1执行."); } //默认构造方法 public ch04_3_4(){ System.out.println("构造方法执行."); }执行顺序:1执行顺序:3
  • 361. 361 //main方法 public static void main(String []argc){ ch04_3_4 ch433 = new ch04_3_4(); } //静态初始化代码块2 static{ size = 9000; System.out.println("静态代码块2执行."); } }执行顺序:2
  • 362. 3627.最终域由修饰符“final”修饰的域,此种域不能被改变,用法格式: final 数据类型 变量名称; 例如:访问修饰 final 数据类型 变量名称;class PhoneCard { final String TYPE_ID=“JPG_TYPE”; double cardNumber; …… }
  • 363. 3638. 常量 (Constants)static与final组合通常用来表示常量。语法格式:例如 static final double PI = 3.141592653589793; static final int MAX_SIZE = 216;修饰 static final 类型 常量名 = <字面量>;按惯例,常量名用大写,如果名称由多个词组成,用“_”连接起来。
  • 364. 364364第四章、继承与多态继承 (构造方法继承)
  • 365. 3653654.4、构造方法继承1.构造方法继承子类可以继承父类的构造方法,但继承遵循下列原则:如果子类没有无参数构造方法,它将继承父类的无参数构造方法作为自己的构造方法。public class A{ public A(){ System.out.println("Constructors: A()."); } public A(int a){ System.out.println("Constructors: A(int a)."); } }父类
  • 366. 366public class B extends A{ }子类class Ch05_4_1 { public static void main(String args[]){ B b; b = new B(); } }实例化类B
  • 367. 367如果有自己的无参数构造方法,则在创建对象时先执行父类的无参数构造方法,然后再执行自己的无参数构造方法。public class A{ public A(){ System.out.println("Constructors: A()."); } public A(int a){ System.out.println("Constructors: A(int a)."); } }父类
  • 368. 368public class B extends A{ public B(){ System.out.println("Constructors: B()."); } public B(int a){ System.out.println("Constructors: B(int a)."); } public B(int a,int b){ System.out.println(“Constructors: B(int a, int b).”); } }A的 子类
  • 369. 369public class C extends B{ public C(){ System.out.println("Constructors: C()."); } public C(int a){ System.out.println("Constructors: C(int a)."); } public C(int a,int b){ System.out.println("Constructors: C(int a, int b)."); } }B的 子类
  • 370. 370class Ch05_4_2 { public static void main(String args[]){ C c; c = new C(); } }实例化类C类A类B类C
  • 371. 371如果子类在其构造方法中要调用父类的有参数构造方法,则使用super关键字在子类构造方法的第一条语句调用,调用格式: super(<参数表>);public class A { public String name = "Class A"; public A(){ System.out.println("构造方法:A()"); } }父类
  • 372. 372public class AA extends A{ public AA(){ System.out.println("构造方法:AA()"); } public AA(int l){ super(l); } }子类调用父类的有参数构造方法类A类AA
  • 373. 3732.设计构造方法利用构造方法在继承中的这些特点,在声明设计类时可以做这样的考虑:不专门定义类自己的构造方法。 定义自己的构造方法并调用父类带参数的构造方法。 在子类实现构造方法的重载。考察下面的代码:
  • 374. 374public class A{ public A(){ System.out.println("Constructors: A()."); } public A(int a){ System.out.println("Constructors: A(int a)."); } }父类
  • 375. 375public class B extends A{ public B(){ System.out.println("Constructors: B()."); } public B(int a){ super(a); } public B(int a,int b){ System.out.println("Constructors: B(int a, int b)."); } }类A类B子类
  • 376. 376public class C extends B{ public C(){ System.out.println("Constructors: C()."); } public C(int a){ super(a); } public C(int a,int b){ super(a,b); } public C(int a,int b, int c){ System.out.println("Constructors: C(int a, int b)."); } }类A类B类C子类
  • 377. 377class Ch05_4_4 { public static void main(String args[]){ System.out.println("Create: A"); A a0 = new A(); A a1 = new A(1); System.out.println("Create: B"); B b0 = new B(); B b1 = new B(1); B b2 = new B(1,2); System.out.println("Create: C"); C c0 = new C(); C c1 = new C(1); C c2 = new C(1,2); C c3 = new C(1,2,3); } }实例化类A B C
  • 378. 378A a0 = new A();A a1 = new A(1);B b0 = new B();B b1 = new B(1);B b2 = new B(1,2);
  • 379. 379379第四章、继承与多态多态 (抽象类)
  • 380. 3803804.5、抽象类1.抽象方法与抽象类抽象类是被abstract声明的类,它可以包含或不包含抽象方法(abstract methods )。public abstract class GraphicObject { // declare fields ……. // declare non-abstract methods abstract void draw(); …… }
  • 381. 381抽象方法是一种声明而不用实现的方法。 例如,方法 abstract void moveTo(double deX,double deY); abstract void move(double deX,double deY); 只用方法声明,而无具体的实现并且用abstract 修饰。
  • 382. 3822.声明抽象类抽象类由abstract修饰,声明与类声明相同,语法格式:public abstract class 类名 extends 类名 implements 接口 { // 声明域 // 声明非抽象(non-abstract)方法 // 声明抽象( abstract)方法 } 声明域 声明非抽象(non-abstract)方法
  • 383. 383抽象方法是有声明但没有实现(没有“{‘},并且紧跟一个“;”号)的方法,声明抽象方法用下面的格式: abstract 类型 方法名称([参数表]);修饰 abstract 类型 方法名称([参数表]);声明抽象( abstract)方法例如下列方法public abstract void draw(); public abstract void resize(); 考察下面的代码:
  • 384. 384public abstract class Book{ protected String name; protected String author; protected String lastDate; protected String edition; protected int currentPageNo; protected int pageNumber; public Book(){ } public abstract void read(); public abstract void read(int pageNo); public abstract void gotoNextPage(); public abstract void gotoPreviousPage(); } 例抽象方法抽象类抽象类抽象方法抽象类
  • 385. 3853.抽象类的类成员抽象类可以包含: 非static的、非final的域。 可以包含已经实现的方法。 static域和static方法,用类名引用它们。 static的、final的域,用类名引用它们。
  • 386. 3864.使用抽象类抽象类提供了一种机制:当需要提供某种更高层次的描述时,用抽象类定义一个通用的,且可被它的所有继承者共享的形式,而具体实现细节由子类完成,抽象类仅确定子类必须实现的方法。使用abstract关键字必须遵循如下规则:不能用于构造方法。 不能用于静态方法和私有方法。 由abstract修饰的方法必须在子类实现。如果不在子类中完全对父类中的抽象方法提供实现,那么子类仍然必须用abstract 修饰声明。 子类不能覆盖超类中的abstract方法。
  • 387. 387(1)抽象类实现接口使用接口时需要实现接口中所有的抽象方法。但在实际应用中往往既要使用接口又不需要实现所有抽象方法,抽象类提供这种需求的解决方案,即用抽象类实现接口,把一个接口变成抽象类。例如 鼠标事件监听接口MouseListener包含抽象方法:mouseClicked、mousePressed、mouseReleased、mouseEntered和mouseExited。现仅需要实现方法mousePressed和mouseReleased,通过声明类名称AbstractMouseListener的类实现。
  • 388. 388import java.awt.event.*; public abstract class AbstractMouseListener implements MouseListener { public void mousePressed(MouseEvent e){ …… } public void mouseReleased(MouseEvent e){ …… } }MouseListener 接口被实现的MouseListener接口方法MouseListener 接口被实现的MouseListener接口方法
  • 389. 389(2)抽象类的类成员抽象类可以包含static修饰的域和方法,即类变量和类方法。这些变量和方法可以通过类名称直接引用,就象对非抽象类中类成员的引用。 例如,下面程序演示引用抽象类AbstractPen的 DEFAULTCOLOR DEFAULTSIZE 成员。这是两个静态成员,具体类声明见AbstractPen.java。
  • 390. 390public class Ch05_5_1 { public static void main(String args[]) { System.out.print("Default-Color of the Pen:"); System.out.println(AbstractPen.DEFAULTCOLOR); System.out.print("Default-Size of the Pen:"); System.out.println(AbstractPen.DEFAULTSIZE); } }
  • 391. 391import java.awt.*; public abstract class AbstractPen { public static Color DEFAULTCOLOR = Color.BLUE; public static int DEFAULTSIZE = 1; public AbstractPen(){ } public static void modifyDefaultColor(Color color){ DEFAULTCOLOR = color; } public static void modifyDefaultSize(int size){ DEFAULTSIZE = size; } public abstract void drawLine(int x1,int y1,int x2,int y2); public abstract void drawRect(int x1,int y1,int x2,int y2); public abstract void drawArc(int x,int y,int r); }
  • 392. 392392第四章、继承与多态继承 (接口)
  • 393. 3933934.6、接口1.Java接口(Java Interface)在软件工程中有一些情况对于截然不同的程序设计组接受“协议”详细说明它们的软件如何相互作用是重要的。每个组应该能过写它们的代码,而不用其他组的代码编写的任何知识。一般来说,接口是这样的协议。 Java语言中接口是像类一样的引用型类型,仅可包含常量、方法签名、嵌套类型。 接口不能被实例化,仅能被类或其他接口扩充(extends)。
  • 394. 394Java语言中接口有一个非常重要的角色。接口不是类树的一部分,尽管它们的工作与类结合。Java程序设计不允许多继承,但接口提供了一种替代方案。考察下面的程序代码:public interface OperateCar { // method signatures int turn(Direction direct, double radius, double speed); int changeLanes(Direction direct, double start, double end); int signalTurn(Direction direct, boolean signalOn); int getRadarFront(double distanceToCar, double speed); int getRadarRear(double distanceToCar, double speed); }定义接口
  • 395. 395public class OperateBMW760i implements OperateCar { public int signalTurn(Direction direct, boolean signalOn) { } public int turn(Direction direct, double radius, double speed){ } public int changeLanes(Direction direct, double start, double end){ } public int signalTurn(Direction direct, boolean signalOn){ } public int getRadarFront(double distanceToCar, double speed){ } public int getRadarRear(double distanceToCar, double speed){ } }实现接口
  • 396. 3962.定义接口接口是抽象类的变体。接口中的所有方法都是抽象的,没有一个有程序体。接口中的方法因为已经隐含为抽象方法,所以声明方法是不用abstract修饰。 接口声明由修饰、interface、接口名称、逗号隔开的父接口列表和接口体。接口的声明方法如下:[修饰] interface 接口 extends 接口1,…… { public static final成员变量 (抽象)方法1; …… }
  • 397. 397修饰 public 表明接口可用于任何包的任何类。 package-private 仅被定义在同名包的类访问。 extends 接口,…… 接口从其他接口扩展产生,Java允许接口从多个其他接口扩充。 接口体部 包含接口中的所有方法的方法声明。接口中的所有方法声明是隐含public,因此public可以省略。 接口可以声明常量,所有定义在接口中的常量隐含public、static和final。这些修饰是可以省略的。
  • 398. 398接口一旦定义并使用就不要试图为它再增加新的方法声明。因为这样会使所有实现原有接口的类不能被编译,除非重新修改这些类。提示
  • 399. 399public interface DoSomethingInterface extends Interface1, Interface2, Interface3 { // constant declarations double E = 2.718282; // base of natural logarithms // method signatures void doSomething (int i, double x); int doSomethingElse(String s); }例常量接口方法
  • 400. 400 public interface Transparency { public static final int OPAQUE=1; public static final int BITMASK=2; public static final int TRANSLUCENT=3; public int getTransparency(); } 例常量接口方法
  • 401. 401例 ch05_6_1设计接口DataTransform用于实现数据传递。 (1)接口要求实现方法: receive(Data data): 接收数据。 send(Data data): 发送数据。 run(): 多线程线程体程序。
  • 402. 402(2)接口包含的数据域成员: INPORT: 接收数据端口。 OUTPORT: 发送数据端口。 FRAMESIZE: 一次接收或发送的数据块字节数,默认1024字节。
  • 403. 403分析接口要求的方法在设计接口时可以直接声明。 有关多线程的线程体方法可以使用Runnable接口实现。 接口只能包含static final常量。因为是作为全局使用,所以访问控制public。
  • 404. 404接口定义public interface DataTransform extends Runnable { public static final int INPORT = 5000; public static final int OUTPORT = 4000; public static final int FRAMESIZE = 1024; public void receive(Data data); public void send(Data data); }源程序文件:DataTransform.java
  • 405. 4053.实现接口接口定义了程序的一种“行为”协议,类通过接口现实现这种协议。在声明类时实现接口,是通过子句implements确定要实现的接口,一个类可以同时实现多个接口,每个接口之间用“,”分隔开。实现接口必须使用implements关键字,具体格式如下:修饰 class 类名 extends 父类名 implements 接口[,接口]{ …… }
  • 406. 406在定义类时,类声明必须实现接口中的所有方法,包括其超级接口中的方法。否则,这个类就必须被声明为抽象类。 通常implements放在extends之后。 提示
  • 407. 407例 实现Ch05_6_1程序中声明的接口,详细程序参考源程序见文件 Ch05_6_1.java 和 DataTransform .java。public class Ch05_6_1 { public static void main(String args[]){ Dot dotA = new Dot(); } }
  • 408. 408public class Dot implements DataTransform{ public Dot(){ …… } public void run(){ try{ …… Thread.sleep(100); }catch(InterruptedException e){ break; } } public void receive(Data data){ …… } public void send(Data data){ …… } }
  • 409. 409例 实现鼠标事件监听接口,显示鼠标位置。源程序见文件Ch05_6_2.java。类声明class Ch05_6_2 extends Frame implements MouseListener{ public Ch05_6_2(){ …… this.addMouseListener(this); } ……. // 实现MouseListener接口方法 }
  • 410. 410实现MouseListener接口方法 public void mouseClicked(MouseEvent e){ printXY("mouseClicked",e); } public void mousePressed(MouseEvent e){ printXY("mousePressed",e); } public void mouseReleased(MouseEvent e){ printXY("mouseReleased",e); } public void mouseEntered(MouseEvent e){ printXY("mouseEntered",e); } public void mouseExited(MouseEvent e){ printXY("mouseExited",e); }
  • 411. 411
  • 412. 4124.重写接口当接口定义完成后,由于某些原因需要为已有接口添加方法从而使接口被重写。这将会引起实现这个接口相关的所有类都必须重写修改,因为所有对该接口的实现被打断,接口不再被实现。。通常,在设计接口开始就尽可能地预测接口所需要的一切并完成它。如果需要重写接口,可以新定义一个接口并用欲重写接口作为父接口。具体参考下面的代码:接口重写重写方法
  • 413. 413public interface DoIt { void doSomething(int i, double x); int doSomethingElse(String s); }原始接口public interface DoItPlus extends DoIt { boolean didItWork(int i, double x, String s); }重写的新接口
  • 414. 4145.接口与抽象类的差异 接口与抽象类不同,它们之间的差异表现在: 接口中不实现任何方法,而抽象类有实现的方法。 类可以实现接口,但它只有一个超级类。 接口不包含在类层次关系中。 不相关的类可以实现相同的接口。 当定义了一个接口也就定义了一种新的引用型数据类型,可以在任何时候使用它。
  • 415. 415415第四章、继承与多态多态性 (包)
  • 416. 4164164.7、包(Packages)1.包的概念包(package)由一组类和接口组成,是相关类型的组,提供访问保护和命名空间管理。类型涉及类、接口、枚举和注解类型。枚举和注解类型是特殊类别的类和接口,所以类型常被简单地引用。 用于管理大型名字空间,以免冲突的工具。有时也将包称为“类库”。 Java系统提供了大量类和接口,允许编程者使用,或根据它们产生新类,这些类和接口被放在几个包中。除此之外,编程人员也可以将自行定义一些包。(1)什么是包
  • 417. 417(2)引用包的原因捆绑类和接口到包中通常的原因包括:你和其他程序员容易地确定这些类型的关系。 你和其他程序员知道在哪找到类型。 你的类型名称不与在其他包中的类型名发生冲突,因为包创建了一新的命名空间。 你可以允许在包总的类型无限制地访问另一其他的类型,但仍然限制包外的类型访问。
  • 418. 4182.创建包创建包,为包你选择一个名称,放置带名称的包语句在每个源文件的顶部,源文件包含你要包含在包中的类型(类、接口、枚举和注解类型)。包语句必须在源文件的第一行。 在每个源文件仅能有一个包语句,并且应用于文件中的所有类型。 语句格式: package 包名称;(1)定义包package 包名称;
  • 419. 419//源程序 Draggable.java package graphics; public interface Draggable { . . . } //源程序 Graphic.java package graphics; public abstract class Graphic { . . . } //源程序 Circle.java package graphics; public class Circle extends Graphic implements Draggable { . . . }例
  • 420. 420(2)命名包包名的所有字符用小写字母。 避免与包中的类名和接口名冲突。 包名称是一个名字或由“.”分隔的名字串。如果是名字串它表示一个存放类或接口的层次目录结构。例如,java.io、org.ms.fl等。 公司或企业用它们的域名作为开始包名,例如com.ex.tu。
  • 421. 421如果在一个源文件放置多个类型,仅一个能是public,并且类型名称与源文件名称相同。 可以像一个public类型那样,包含non-public类型在相同文件里(通常不提倡这样,除非所有non-public类型比较小并且与某个public类型相关),但仅public类型可从包的外面访问。 所有顶层的,非public类型将是package private(包私有) 。 (3) 包成员
  • 422. 422例//in the Draggable.java file package graphics; public interface Draggable { . . . } //in the Circle.java file package graphics; public class Circle extends Graphic implements Draggable { . . . }
  • 423. 4233.使用包成员包含在包中的类型称作包成员。从包外面使用包public成员必须:通过完全限定名引用包成员,即“包名字.成员”。 例如, java.io.InputStream in; java.lang.String name; 等。 包名.成员;
  • 424. 424或者,引入用包成员,即“import 包名字.成员”。 例如, import java.io.InputStream; import java.lang.String; InputStream in; String name; 等。import 包名.成员;
  • 425. 425或者,引入整个包中所有成员,即“import 包名字.*”。 例如, import java.io.*; import java.lang.*; InputStream in; String name; 等。import 包名.*;
  • 426. 4264.static import 语句有时需要频繁从一个或两个类访问static final域(常量)和static方法,类名作为前缀名反复出现在代码中。static import语句提供引入常量和静态方法而不用类名作为前缀的途径。语句语法格式:import static 包名.成员;例如, import static java.lang.Math.*; double r = cos(PI * theta);
  • 427. 427对于外围类的嵌套类,也允许用import引入,即“import 包名字.*”,但要经过两个步骤。 例如,graphics.Rectangle 类包含Rectangle.DoubleWide 和Rectangle.Square两个嵌套类,要引入 graphics.Rectangle 类以及嵌套类,用下面的步骤。 import graphics.Rectangle; import graphics.Rectangle.*; 。
  • 428. 4285.管理源文件和类文件Java平台的许多实现依赖于分层的文件系统管理类和源文件,尽管在Java语言规范没有要求这些。基本策略包括:将class、interface、 enumeration或 annotation 类型代码放置于简单的Text文件中,文件名称是类型名称,扩展名称“.java”即Java源程序文件。 例如,接口 Runnable,程序代码 public interface Runnable { public void run(); }文件名: Runnable.java
  • 429. 429将源程序文件放置在一个目录下,目录名与包名相似,即目录名与包名构成映射关系。例如,包名称为 com.example.graphics 对应的目录名应该是 ....\com\example\graphics\ 。
  • 430. 430430第四章、继承与多态继承 (Exception与异常处理)
  • 431. 4314314.9、 Exception与异常处理1.什么是例外(Exception)Exception是在程序执行期间发生的打乱正常程序指令流程的事件。exception 是 “exceptional event.”的缩写。 (1)exception(2)抛出例外(throwing an exception )当在方法中发生错误时,方法会创建一个object并把它交给运行系统,这个object称作“exception object ”。它包含有关错误的信息:错误类型和错误发生时程序的状态。这种创建exception对象,并传递给运行系统称作“throwing an exception ”。
  • 432. 4322.捕捉和处理例外要处理特殊的异常,将可能够抛出异常的代码放入try块中,然后创建相应的catch块的列表,每个可以被抛出异常都有一个。如果生成的异常与catch中提到的相匹配,那么catch条件的块语句就被执行。在try块之后,可能有许多catch块,每一个都处理不同的异常。 try { // 可能产生错误抛出例外的代码 } catch (exception-type e) { // 处理例外的代码 } finally { …… }
  • 433. 433public static void main (String args[]) { int i = 0; String greetings [] = { "Hello!", "No", "WORLD!!"}; while (i < 4) { try { System.out.println (greetings[i]); } catch (ArrayIndexOutOfBoundsException e){ System.out.println( "Re-setting Index Value"); i = -1; } finally { System.out.println("This is always printed"); } i++; } // end while() } // end main() 例产生ArrayIndexOutOfBoundsException处理ArrayIndexOutOfBoundsException
  • 434. 434(1)try代码段所有可能产生错误抛出exception的代码放在 try{…} 代码段内,程序样式如下:try { code blocks . . . }例如,try { out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { out.println("Value at: = " + vector.elementAt(i)); } }
  • 435. 435(2)catch 代码段Exception处理放在try代码块后面的一个或多个catch代码块内,程序样式如下:try { } catch (ExceptionType name) { exception处理代码 } catch (ExceptionType name) { exception处理代码 } ……
  • 436. 436ExceptionType - 声明exception的类型。 Name - 捕获的exception对象的引用。try { …… } catch (FileNotFoundException e) { System.err.println("FileNotFoundException:"+ e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); }例如,
  • 437. 437(3)finally 代码段当try代码块退出时finall代码块总会被执行。通常放置程序的清除代码在这个地方。例如,try { …… } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught " } finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } }
  • 438. 4383.处理或声明规则 (1)处理或声明规则 : 用try-catch-finally块来处理异常; 使用throws子句声明代码能引起一个异常 。(2)程序员可以做满足该要求的两件事: 第一,通过将try{}catch(){}块纳入其代码中,在这里捕获给被命名为属于某个超类的异常,并调用方法处理它。即使catch块是空的,这也算是处理情况。
  • 439. 439 第二,让被调用的方法表示它将不处理异常,而且该异常将被抛回到它所遇到的调用方法中。它是按如下所示通过用throws子句标记的该调用方法的声明来实现的: public void troublesome() throws IOException 关键字throws之后是所有异常的列表,方法可以抛回到它的调用程序中。尽管这里只显示了一个异常,如果有成倍的可能的异常可以通过该方法被抛出,那么,可以使用逗号分开的列表。
  • 440. 4404.创建自己的异常 用户定义异常是通过扩展Exception类或它的其他子类来创建的。这种异常类可以包含一个“普通”类所包含的任何东西。抛出自定义异常对象在出现错误的位置加入代码:throw new 自定义异常构造器;从Exception或它的子类派生自己的exception类。 用throw抛出异常对象。 捕获抛出的异常对象。
  • 441. 441class InputDataException extends Exception{ public InputDataException(String message){ super(message); } public InputDataException(String message, Throwable cause){ super(message,cause); } }(1)创建异常类创建的exception类的父类应是Throwable 类,但通常用Exception类或它的子类。
  • 442. 442(2)抛出异常在方法中抛出exception对象,抛出的位置由方法的具体代码需要来确定。如果需要抛出异常对象,应该: 创建exception对象。 用throw抛出,即throw exception对象。 在方法签名后的throws后面列出exception类。 但通常是将两者放在一条语句中完成,即: throw new exception类(); 考察下面的程序代码。
  • 443. 443class InputData { private static int len = 10; private static byte []buffer; public static int InputInteger() throws IOException, InputDataException{ buffer = new byte[len]; System.in.read(buffer); String data = new String(buffer,0,buffer.length); data = data.trim(); try{ return Integer.parseInt(data); }catch(NumberFormatException nfe){ throw new InputDataException("格式不正确",nfe); } } }抛出异常
  • 444. 444(3)捕获处理异常import java.io.*; public class ExcepSample { public static void main(String[] args) { try{ System.out.println("请输入一个整数(xxxxx):"); System.out.println("input:" + InputData.InputInteger()); }catch(IOException e){ e.printStackTrace(); }catch(InputDataException ide){ ide.printStackTrace(); } } }捕获异常
  • 445. 445445第四章、继承与多态多态 (方法继承、覆盖、隐藏)
  • 446. 4464464.3、方法继承、覆盖、隐藏子类继承了父类中所有的非私有方法,允许在子类重新定义父类中的实例方法,隐藏父类中的类方法。 “多态”是指一个程序中同名的不同方法共存。在面向对象程序中,多态的实现方式有: 方法覆盖(override) 重载(overload)
  • 447. 4471.方法继承子类继承父类所有的public 和 protected 方法,而无论这个类是否与父类在同一个包中。 如果子类与父类在同一个包中,它也继承类父类的package-private 方法。 在子类中可以通过成员的名称直接引用父类的方法或者用“this.方法名称”引用父类的方法。下图表示上述关系:
  • 448. 448域方法域方法类B类A非私有成员新添成员类B成员域方法类A类A成员派生超类子类
  • 449. 449public class A { protected int x; public A(){ x=100; m = 2.0; } private void isNum(){ …… } }public class B extends A { protected int y; public B(){ x = 10; } } 类B是由类A派生产生的,所以类B包含了类A的所有非私有成员。 类A的isNum()方法在类B中是不允许被使用的。
  • 450. 450例 ch05_3_1 编写一个在运行在网页中绘制由圆组成的图像的Applet程序,程序执行后显示如下图所示。
  • 451. 451 分析运行在网页中的Applet程序由java.awt.applet中的Applet类派生产生,绘制图性能高形在paint()方法。 以Applet父类,通过继承创建程序,添加程序要求的功能。 类名称: Ch05_3_1 。
  • 452. 452 实现import java.awt.*; import java.applet.*; public class Ch05_3_1 extends Applet { private Color []color = {Color.RED,Color.BLUE, Color.GREEN,Color.ORANGE, Color.PINK}; private int width,height; private int d; public void init(){ } public void paint(Graphics g){ int x,y,i; width = getWidth(); height = getHeight(); d = ((width>height? height:width))/5;(源程序: Ch05_3_1.java)
  • 453. 453 public void paint(Graphics g){ int x,y,i; width = getWidth(); height = getHeight(); d = ((width>height? height:width))/5; x = 0; y = 0; width = (width>height? height:width); for(i=0;i<5;i++){ g.setColor(color[i]); g.drawArc(x,y,width,width,0,360); width = width - d; x = x + d; y = y + d; } } }继承于Applet的成员
  • 454. 4542.方法覆盖在子类中的实例方法与在父类中的实例方法有相同的签名和返回类型时,称作覆盖(overriding)了类父的方法。 覆盖方法是重新按照超类中方法的相同参数表和返回值重新定义的同名方法。覆盖方法又称为重写方法。 当在子类中的覆盖一个父类的方法时,用@Override 注解符通知编译期在父类你想要覆盖的方法。如果因为某种原因编译器探测到在父类中方法不存在,它将产生错误。
  • 455. 455public class X { …… public boolean isOverrid(){ …… } …… }public class Y extends X { …… @Override public boolean isOverrid(){ …… } …… }覆盖方法覆盖方法其形式如下:
  • 456. 456public class myApplet extends Applet{ @Override public void init() { } @Override public void start() { } @Override public void stop() { } @Override public void paint(Graphics g) { super.paint(g); } }被覆盖的父类 Applet的方法例
  • 457. 457在调用覆盖的方法时,被调用的覆盖方法的版本只有一个,就是子类中的覆盖方法。考察下面的程序。public class Ch05_3_2 { public static void main(String args[]){ X x = new X("X-Object"); x.displayClassMessage(); Y y = new Y("Y-Object"); y.displayClassMessage(); } }
  • 458. 458public class X { protected String instanceName = "Un-named"; public X(){ System.out.println("Create X object."); } public X(String name){ instanceName = name;; } public void displayClassMessage(){ printClassName(); printInstanceName(); } public void printClassName() { System.out.println("Class:" + getClass().getName()); } public void printInstanceName() { System.out.println("Instance:" + instanceName); } }
  • 459. 459public class Y extends X { public Y(){ System.out.println("Create Y object."); } public Y(String name){ instanceName = name;; } @Override public void printClassName() { System.out.println("Class:" + getClass().getName()); } }
  • 460. 4603.方法隐藏如果在子类中定义与父类有相同签名类方法,这个方法就隐藏(Hides)父类中的方法。 被调用的隐藏方法的版本取决于是从子类或父类。public class Animal { public static void testClassMethod() { System.out.println("The class method in Animal."); } public void testInstanceMethod() { System.out.println("The instance method in Animal."); } } 静态方法(类方法)非静态方法(实例方法)
  • 461. 461public class Cat extends Animal { public static void testClassMethod() { System.out.println("The class method in Cat."); } public void testInstanceMethod() { System.out.println("The instance method in Cat."); } public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.testInstanceMethod(); } }静态方法(类方法)非静态方法 (实例方法)静态方法(类方法)非静态方法 (实例方法)执行结果: The class method in Animal. The instance method in Cat.
  • 462. 4624.父类对象与子类对象的转换父类对象和子类对象之间在一定条件下是可以相互转换的。这种转换遵循下列规则:子类对象可以看成是其父类的一个对象。 父类对象不能当作是其一子类的对象。 在方法参数中,如果方法参数父类的对象,在调用方法时可以用其子类作为实际的参数。 如果父类对象引用指向的实际是一个子类对象,那么这个父类对象的引用可以用强制类型转换转化成子类对象的引用。
  • 463. 463class superClass { int x; …… }class subClass extends superClass{ int y; char ch; …… }父类子类下面程序片段显示对象的类型转换:
  • 464. 464464public class useSuperSub { superClass sc,sc_ref; subClass sb,sb_ref; …… sc = new superClass(); sb = new subClass(); sc_ref = sb; sb_ref = (subClass)sc_ref; …… }
  • 465. 465465第四章、继承与多态继承 (继承)
  • 466. 4664664.1、继承继承是面向对象技术的重要特点之一。 继承是两个类之间的一种关系,当一个类获取另外一个类中所有非私有数据和操作的定义作为自己的部分或全部成分时,则称这两个类之间具有继承关系。被继承的类称为父类或超类,继承类父类的所有数据和操作的类称为子类或派生类。 一个父类可以同时拥有多个子类,此时父类实际上是所有子类的公共域和公共方法的集合。 一个类可以有一个父类,也可以有多个父类,这就是所谓的单继承和多继承的问题。
  • 467. 467类A域1 域2 ……方法1 方法2 ……类B域1 域2 ……方法1 方法2 ……类C域1 域2 ……方法1 方法2 ……继承父类子类C继承子类B
  • 468. 468类B域1 域2 ……方法1 方法2 ……类A域1 域2 ……方法1 方法2 ……类C域1 域2 ……方法1 方法2 ……多继承
  • 469. 469类A域1 域2 ……方法1 方法2 ……类B域1 域2 ……方法1 方法2 ……单继承
  • 470. 4701.Java类继承Java中继承由关键字extends实现。类声明时用extends关键字指出超类,通过继承产生类的一般形式: Java不能支持多继承关系,一个子类只能有一个超类。[修饰] class 类名称 extends 超类名称 { 域(字段)声明 方法声明 …… }
  • 471. 471修饰 修饰决定着类在程序运行中被处理的方式,控制着变量或对象的可访问性。可以使用默认的修饰符,也可以显式指定。这里主要有如下种修饰符: public 共有的。 private 私有的。 protected 保护的。 默认 包私有。 static 静态的。 final 最终的。 abstract 抽象的。不能被实例化。 提示:有关修饰的详细内容复习前面的相关章节。
  • 472. 472类名称 要创建的子类的类名称。 超类名称 被继承的类名称,即父类或超类的名称。所有Java类都以Object为超类,即使声明类时未指明超类编译器也会以Object类为默认超类。提示:类名称和超类名称的命名,都必须符合Java标识符的命名规则和Java惯例,具体请复习类声明相关章节。
  • 473. 473例 Person类表示人,Man和Women可以从它派生出表示男人和女人。PersonManWomen考查下面表示这种关系的程序代码。
  • 474. 474public class Person{ protected String name; protected float height; protected float weight; protected float age; protected String sex; public Person(){ } public Person(String name, float h){ this.name = name; height = h; } }Person类
  • 475. 475public class Man extends Person{ public Man(){ } public Man(String name, float h){ super(name,h); sex = “男”; } }Man类Man类和对象包含了其父类Person类的所有成员,即成员变量和方法。 Man类和对象可以访问Person类的非private成员。Person类的实例变量Person类的构造方法
  • 476. 476public class Women extends Person{ public Man(){ } public Man(String name, float h){ super(name,h); sex = “女”; } }Women类Women类和对象包含了其父类Person类的所有成员,即成员变量和方法。 Women类和对象可以访问Person类的非private成员。Person类的实例变量Person类的构造方法
  • 477. 4772.Java平台类层次在Java程序中,所有类都直接或间接地是Object类的子类,它定义在java.lang包。Object类是Java程序中所有类的顶层超类。下图是Java平台类层次图。
  • 478. 4783.访问控制子类继承(或包含)父类的全部成员(域、方法和嵌套类)。 通常不会允许子类访问父类中的全部成员,子类对父类成员的访问会受到一些限制。这样做的目的是为了保护父类免受不必要的干扰。 下表列出了父类和可以被子类访问的成员情况:超类成员publicprotected默认private子类可 访问性√√√×
  • 479. 479考察下面类的关系及对成员的访问。 已知有两个类:X类和Y类。其中Y类是由X类扩展而成,即Y类是X类的派生类,X类是Y类的超类,其关系如下图所示。X 类Y 类超类子类(继承)X类非private成员。 Y类成员。X类成员。
  • 480. 480public class X{ private int type; protected double value; public String name; public X(){ type = 0; name = “un-name”; value = 0.0; } public void setType(int type){ this.type = type; } }X 类
  • 481. 481public class Y extends X{ int type; public Y(String n, double v, int t){ value = v; name = n; setType(t); } public double getValue(){ return value; } public String getName(){ return name; } }Y类Y类的成员超类 X的成员超类 X的成员超类 X的成员
  • 482. 4824.super关键字super关键字表示超类的引用,可用super: 访问超类成员。 在子类构造方法使用超类构造方法。 考察下列代码:public class Superclass { public Superclass(){ } public void printMethod() { System.out.println("Printed in Superclass."); } }超类
  • 483. 483public class Subclass extends Superclass { public Subclass(){ super(); } //overrides printMethod in Superclass public void printMethod() { super.printMethod(); System.out.println("Printed in Subclass"); } public static void main(String[] args) { Subclass s = new Subclass(); s.printMethod(); } }子类调用父类方法调用父类构造方法
  • 484. 484484第四章、继承与多态继承 (域的继承与隐藏)
  • 485. 4854854.2、域的继承与隐藏1.域的继承子类继承父类所有的 public 和 protected 成员,而无论这个类是否与父类在同一个包中。 如果子类与父类在同一个包中,它也继承类父类的package-private 成员。 在子类中可以通过成员的名称直接引用父类的成员或者用“this.成员名称”应用父类的成员。下图表示上述关系:
  • 486. 486域方法域方法类B类A非私有成员新添成员类B成员域方法类A类A成员派生超类子类考察下面的代码:
  • 487. 487public class A { private boolean m; protected int x; public A(){ x=100; m = 2.0; } }public class B extends A { protected int y; public B(){ x = 10; } } 类B是由类A派生产生的,所以类B包含了类A的所有非私有成员。 类A的m域在类B中是不允许被使用的。
  • 488. 488例 ch05_2_1 编写一个Windows标准样式的窗口程序。程序执行后显示如下图所示。
  • 489. 489 分析编写窗口程序在涉及到窗口的注册、创建、显示和事件处理等许多繁琐的步骤。而在Java程序设计中已经为提供了创建窗口程序所必须的程序,它们被封装在java.awt.Frame和javax.swing.JFrame两个类内。 以Frame或JFrame为父类,通过继承创建窗口,添加程序要求的功能。 这里程序实现窗口建立和显示的类名称:NormalWin。
  • 490. 490import java.awt.*; import java.awt.event.*; public class NormalWin extends Frame { public NormalWin() { addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ dispose(); System.exit(0); } }); } }NormalWin类源程序: NormalWin.java 实现
  • 491. 491源程序: Ch05_2_1.javapublic class Ch05_2_1 { public static void main(String args[]){ System.out.println("Starting Ch05_2_1..."); NormalWin mainFrame = new NormalWin(); mainFrame.setSize(400, 400); mainFrame.setTitle("Normalized Window"); mainFrame.setVisible(true); } }主程序继承于Frame的成员
  • 492. 4922.域的隐藏(Hiding Fields )在子类中重新定义一个与从父类那里继承来的名字完全相同的域,称为域的隐藏。 如果子类与父类有相同名字的成员变量,在子类中就会隐藏父类中的同名变量,尽管他们可能有不同的类型。 在子类中不能简单地通过变量名称引用父类中被隐藏的成员变量。要在子类访问被隐藏的父类中的域必须通过关键字super引用。考察下面的代码:
  • 493. 493域:x方法域:x方法类B类A非私有成员新添成员类B成员域:x方法类A类A成员派生超类子类考察下面的代码:被隐藏
  • 494. 494public class A { protected int x; public A(){ x=100; } }public class B extends A { protected int x; public B(){ x = 10; super.x = 10; } } 类B是由类A派生产生的,因为它们都有一个成员变量x,所以类B的成员x实际上隐藏了类A的成员x。 在子类中,用名称 x 引用的类B的x域;super.x引用的是类A的x域。
  • 495. 495例 ch05_2_2 修改已知类Point,将表示位置的double类型的域ox和oy修改成int类型的同名域,新类名称:IPoint.如下图所示。Point^ox:double; ^oy:double; …………IPoint^ox:int; ^oy:int; …………
  • 496. 496public class Point{ protected double ox; protected double oy; public Point(){ } public Point(double ox,double oy){ this.ox = ox; this.oy = oy; } …… }源程序: Point.javadouble类型域:ox和oy。Point类
  • 497. 497public class IPoint extends Point{ protected int ox; protected int oy; public IPoint(){ } public IPoint(int ox,int oy){ this.ox = ox; this.oy = oy; } …… }源程序: IPoint.java用int类型重新定义域:ox,oy。 父类的同名域在此被隐藏。IPoint类
  • 498. 498public class Ch05_2_2{ public static void main(String args[]) { Point point = new Point(214.456, 694.22); System.out.println("Point Object"); System.out.println(" ox =" + point.getX()); System.out.println(" oy =" + point.getY()); IPoint ipoint = new IPoint(800, 700); System.out.println("IPoint Object"); System.out.println(" ox =" + ipoint.getX()); System.out.println(" oy =" + ipoint.getY()); } }主程序源程序: ch05_2_2.java
  • 499. 499执行结果
  • 500. 500500第四章、继承与多态继承与多态 (综合实例)
  • 501. 5015014.10、综合实例1.实例 1绘制函数f(x)当x∈[0,Xmax]时曲线。函数f(x) f(x) = (cos(x/5)+sin(x/7)+2)Ymax/4 曲线图如下:
  • 502. 502 分析函数计算比较简单,所用到的sin和cos函数直接调用类Math中对应函数。 程序的难点是绘制曲线图。因为不能直接用像素点描出曲线,所以曲线绘制稍微复杂。 曲线绘制采用直线线段逼近方法绘制。即形x1与x2平分成n等份dx,绘制点Px与Px+dx之间的连线。
  • 503. 503 抽象与封装将函数计算用专门的方法f实现。 绘制曲线图。因为不能直接用像素点描出曲线,所以曲线绘制采用直线线段逼近方法绘制。即形x1与x2平分成n等份dx,绘制点Px与Px+dx之间的连线。 函数相关的数据包括自变量x及x的最大最小值,y的最大值。 将上述内容均封装到类Fx。
  • 504. 504 确定数据成员(域)private double minX,maxX; private double maxY; private int nums = 5; private double step = 2.0;x取值范围用实例变量minX和maxX表示。 函数值的最大值用实例变量maxY表示。 x变量的变化率用step表示,默认值2.0。 两个相邻x值可划分的等份数用nums表示,默认值5. 所有成员为private。
  • 505. 505 确定方法属性方法: (无) 构造方法:提供无参数构造方法和有三个参数的构造方法,即: Fx() Fx(Fx(double x1, double x2, double maxY) 操作方法: f(double x),计算函数值。 drawFx(Graphics g),绘制函数自变量x在minX之间maxX的曲线图。
  • 506. 506import java.awt.*; import static java.lang.Math.*; public class Fx { private double minX,maxX; private double maxY; private int nums = 5; private double step = 2.0; public Fx(){ } public Fx(double x1, double x2, double maxY){ this.minX = x1; this.maxX = x2; this.maxY = maxY; } Java实现类Fx域构造方法
  • 507. 507 public double f(double x){ return (cos(x/5.0)+sin(x/7.0)+2.0)*maxY/4.0; } 函数值方法
  • 508. 508 public void drawFx(Graphics g){ double x,x1,x2; double dx,dx1,dx2; x = minX; x2 = x; while(x<=maxX){ x1 = x; dx = (x2-x1)/nums; for(int i=0;i
  • 509. 509import java.awt.*; import java.applet.*; public class Ch05_10_1 extends Applet{ private Fx fx; public void init(){ } public void start(){ fx = new Fx(0,getSize().width,getSize().height); } public void paint(Graphics g){ Font font = g.getFont(); g.setFont(new Font("黑体",Font.BOLD,20)); g.setColor(Color.BLUE); g.drawString(“绘制函数f(x)当x∈[0,Xmax]时曲线。",10,30); 类Ch05_10_1
  • 510. 510 g.drawString("f(x) = (cos(x/5)+sin(x/7)+2)Ymax/4 ",10, 50); g.setFont(font); g.setColor(Color.RED); fx.drawFx(g); } }
  • 511. 511
  • 512. 5122.实例 2运行在Web网页中的时钟,样式如图:(此程序来源于JDK附带的示例)
  • 513. 513 分析时钟画面用图形绘制,包括表盘、指针和刻度等。 时钟时间显示动态更新,所以需要使用线程不断从系统获得当前时间。 系统时间通过类Date对象获得。 要能够嵌在Html页面中运行,程序必须从类Applet派生,即创建Applet程序。 线程通过实现接口Runnable实现。
  • 514. 514 抽象与封装 确定数据成员(域)程序嵌在Html页面中,可以看成是浏览器的一个插件,因此把时钟封装成相对独立的插件。程序稍微有些复杂,这里仅给出主要的数据成员,其他成员参考源程序Clock.java。Thread timer; 线程对象引用,刷新时钟画面显示,更新时间值。 int lastxs,lastys,lastxm,lastym,lastxh,lastyh; 时、分、秒指针起始和结束点坐标值。
  • 515. 515Date currentDate; 类Date对象,返回/记录当前日期和时间。 Color handColor; 时针、刻度和表盘颜色。 Color numberColor; 秒针和数字颜色。 int xcenter = 80, ycenter = 55; 时钟表盘中心位置,默认在applet区域80,55。
  • 516. 516 确定方法覆盖类Applet方法: init() start() stop() update() paint() 实现接口Runnable方法: run()
  • 517. 517 Java实现 初始化,在init()方法中完成,主要工作://设置日期-时间显示格式。 formatter = new SimpleDateFormat ("EEE MMM dd hh:mm:ss yyyy", Locale.getDefault()); //返回当前日期并设置日期-时间显示串。 currentDate = new Date(); lastdate = formatter.format(currentDate); //设置时钟表盘字体、颜色及指针颜色。 clockFaceFont = new Font("Serif", Font.PLAIN, 14); handColor = Color.blue; numberColor = Color.darkGray;
  • 518. 518 页面初始化,在start()方法中完成,主要工作://创建线程对象并启动 timer = new Thread(this); timer.start() 页面停止,在stop()方法中完成,主要工作://清除线程 timer = null;
  • 519. 519 定时刷新页面,在run()方法中完成,主要工作://建立线程体循环,每100ms循环一次。 Thread me = Thread.currentThread(); while (timer == me) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { } //刷新页面 repaint(); }
  • 520. 520绘制时钟表盘、刻度和指针,在paint()方法中完成,主要工作://绘制表盘 g.setColor(handColor); g.drawArc(xcenter-50, ycenter-50, 100, 100, 0, 360); //绘制刻度数字 g.setColor(numberColor); g.drawString("9", xcenter-45, ycenter+3); g.drawString("3", xcenter+40, ycenter+3); g.drawString("12", xcenter-5, ycenter-37); g.drawString("6", xcenter-3, ycenter+45);
  • 521. 521 //显示日期-时间串 g.setColor(numberColor); g.drawString(lastdate, 5, 125); //绘制秒针 g.drawLine(xcenter, ycenter, lastxs, lastys); //绘制分针和时针 g.setColor(handColor); g.drawLine(xcenter, ycenter-1, lastxm, lastym); g.drawLine(xcenter-1, ycenter, lastxm, lastym); g.drawLine(xcenter, ycenter-1, lastxh, lastyh); g.drawLine(xcenter-1, ycenter, lastxh, lastyh);
  • 522. 522获得当前时间,计算表针绘制坐标,绘制指针,在update ()方法中完成,主要工作://获得当前日期-时间 currentDate = new Date(); //从formatter中分离出当前时间:时、分、秒。 formatter.applyPattern("s"); s = Integer.parseInt(formatter.format(currentDate)); formatter.applyPattern("m"); m = Integer.parseInt(formatter.format(currentDate)); formatter.applyPattern("h"); h = Integer.parseInt(formatter.format(currentDate));
  • 523. 523//计算秒针绘制坐标 xs = (int) (Math.cos(s * Math.PI / 30 - Math.PI / 2) * 45 + xcenter); ys = (int) (Math.sin(s * Math.PI / 30 - Math.PI / 2) * 45 + ycenter); //计算分针绘制坐标 xm = (int) (Math.cos(m * Math.PI / 30 - Math.PI / 2) * 40 + xcenter); ym = (int) (Math.sin(m * Math.PI / 30 - Math.PI / 2) * 40 + ycenter); //计算时针绘制坐标 xh = (int) (Math.cos((h*30 + m / 2) * Math.PI / 180 - Math.PI / 2) * 30 + xcenter); yh = (int) (Math.sin((h*30 + m / 2) * Math.PI / 180 - Math.PI / 2) * 30 + ycenter); //设置日期-时间串 formatter.applyPattern("EEE MMM dd HH:mm:ss yyyy"); today = formatter.format(currentDate);
  • 524. 524//绘制日期-时间串 g.setColor(numberColor); g.drawString(today, 5, 125); //绘制秒针 g.drawLine(xcenter, ycenter, xs, ys); //绘制分针和时针 g.setColor(handColor); g.drawLine(xcenter, ycenter-1, xm, ym); g.drawLine(xcenter-1, ycenter, xm, ym); g.drawLine(xcenter, ycenter-1, xh, yh); g.drawLine(xcenter-1, ycenter, xh, yh);
  • 525. 525//主要的数据成员 lastxs = xs; lastys = ys; lastxm = xm; lastym = ym; lastxh = xh; lastyh = yh; lastdate = today; currentDate = null;
  • 526. 526 程序类层次AppletClockRunnable-timer ……+init() +start() +update() +paint() ……
  • 527. 527 执行ClockApplet程序是不能独立运行的,必须嵌在HTML中由浏览器解释执行,因此必须用HTML标记在网页中嵌入Java类名称。执行Clock.class类的HTML代码如下:…… ……
  • 528. 528第五章、Applet程序Applet类
  • 529. 5295.1、Applet类 Java小程序Applet运行在Web浏览器,即它可以嵌入在IE或Netscapore中运行,做为Web浏览器的一部分使用。使用Applet可以为网页添加许多丰富、有用的功能。要编写Applet程序,首先要了解它的一些特性和相关的数据及函数。 1.类层次关系: Applet程序通过Applet继承产生。Applet类来源于图1所表示的关系。
  • 530. 530java.lang.objectjava.awt.compoment java.awt.contairnerjava.awt.panel java.applet.Applet类Applet类层次关系 Applet程序
  • 531. 5312.Applet开始与结束: applet的开始是随含有applet程序的网页(web页面)加载而开始,此时完成初始化和启动。用户离开此页面时applet停止运行,关闭浏览器或重新加载该网页时applet终止。Applet的活动周期用图说明。paint(graphics g) Web 浏览器init()start()stop()destroy()
  • 532. 5323.Applet与Java应用程序区别:与所在的主机进行网络连接。 只能运行在web浏览器。 在同一web页面中激活其他applet。 可播放声音与动画。
  • 533. 5334.主要成员变量(属性): appletURL:applet对应的URL。 documentURL:包含applet的网页所对应的RUL。 fgColor:显示颜色。 gColor:背景颜色 font:字体 height:applet显示区域高度。 width:applet显示区域宽度。 item:显示applet的AppletDisplayItem框架名。 tag:调用applet的HTML标记
  • 534. 5345.主要成员方法(函数): 函 数 原 型描 述参 数void destroy()撤消void init()初始化void start()开始void stop()停止AppletText getAppletContext()返回Applet环境String getAppletInfor()返回Applet信息
  • 535. 535函 数 原 型描 述参 数URL getCodeBase()返回applet本身的URLURL getDocumentBase()返回html文档的URLString getParamenter(String name)返回html中传给applet的参数name参数名称String[][] getParamenterInfor()返回参数信息Audioclip getaudioClip(URL url)返回声音片段对象url-声音文件的URL
  • 536. 536Audioclip getaudioClip(URL url,String name)返回声音片段对象url-声音文件的URL name-文件名称Image getImage(URL url)返回图形对象url-图形文件的URLImage getImage(URL url,String name)返回图形对象url-图形文件的URL name-文件名称void showStatus(String msg)在浏览器状态栏显示状态信息msg- 信息文字
  • 537. 537第五章、Applet程序Applet程序结构与运行
  • 538. 5385.2、 Applet程序结构与运行 1.Applet程序格式 Applet程序因为没有main()函数所以不能单独运行,必须由web浏览器调用执行。编写程序必须通过: 继承Applet类 覆盖init() start() stop() destroy()和paint() 等方法,由web浏览器程序执行时自动调用。applet程序的基本结构如下:
  • 539. 539import java.awt.*; import java.applet.*; public class 类名 extends Applet { //程序装载时被调用 public void init() { } //HTML文档关闭时被调用 public void stop() { } //HTML文档显示时被调用 public void start() { } //HTML浏览器退出时被调用 public void destroy(){ }
  • 540. 540 //applet显示时被调用 public void paint(Graphics g){ …… } // 其他方法 …… } 在编写applet程序时,程序中列出的方法不是每个方法都必须使用,可根据需要通过覆盖重写相应的方法。
  • 541. 541import java.awt.*; import java.applet.*; public class Sample3 extends Applet { public void paint(Graphics g){ g.drawString("JavaApplet 欢迎你!!", 50, 60 ); } } 这个程序只需简单地显示一个字符串,没有复杂要求,更没有需要初始化的变量或操作,因此只覆盖了paint方法。例
  • 542. 5422.运行Applet程序 运行小程序必须要有HTML文件,Java小程序是嵌入在网页中,必须由WWW浏览器调用执行。当前HTML标准均支持Applet程序调用标记: [
  • 543. 543程序以Sample3_2.java命名,用javac编译成类文件Sample3_2.class,然后编写下面用来调用例题的HTML文件Sample3_2.html。
  • 544. 544
  • 545. 545第五章、Applet程序Applet程序编写方法
  • 546. 5465.3、Applet程序编写方法编写applet是件很轻松的时,只要按下面的步骤就可以: 给你的类起一个名字,然后由Applet派生,先写出类的框架:public class 类名称 extends Applet { 在此添入变量; 在此添入方法; …… }
  • 547. 547分析一下你的任务,确定并定义一些变量在“在此添入变量;”处。 考虑从哪里开始你的任务,一般非绘图处理从start()方法开始,绘图处理从start()方法开始。可以在这两个方法中直接加入你的代码,也可以调用其他方法,包括你定义的方法。 如果有一次性的初始设置的变量或操作,应在init()方法进行。
  • 548. 548例 已知梯形的上底、下底长度和高分别为L1、L2和H,求该梯形的面积和周长。 分析: 将梯形做为一个对象对待,描述它的数据有上底、下底长度、高、周长、面积和位置等,其中的有些属性可以通过某些方法求得。下面按Java的要求建立类,描述这个梯形。HL1L3L2
  • 549. 549
  • 550. 550运行程序要使用下列HTML代码:
    程序的运行结果如图
  • 551. 551第五章、Applet程序图像显示与声音播放
  • 552. 5525.4、图像显示与声音播放 1.图象显示 在java程序里显示一幅图象,无论图象是何种格式,显示它只要按下面方法做就可以了。 定义一个Image变量。 用applet的getImage()方法装入图象。 使用Graphics对象的drawImage()方法绘制图象。
  • 553. 553具体程序代码如: …… Image m_image=null; …… m_image=getImage(图象文件的URL,图象文件名); …… Graphics对象引用.drawImage(m_image,x,y,this); 提示:该方法最好在paint()方法中使用
  • 554. 554例 显示图象的简单例子。 HTML文件文件名称Sample3_4.html,程序执行结果见图
    演示如何在Applet中显示图象
  • 555. 555
  • 556. 556 在Applet中提供通过AudioClip接口类和play()方法来播放一段音乐。具体的方法是这样的:2.播放声音[1].play()方法播放:该方法有两种形式 public void play(URL soundUrl) public void play(URL soundUrl,String soundName) 方法的参数soundUrl为声音文件所在的地址,soundName为声音文件名称。
  • 557. 557[2].通过AudioClip接口类播放声音: AudioClip是一个接口,它提供一些方法供播放声音使用。使用它必须提供相应方法的实现,因为所提供的方法为抽象方法。Applet的getAudioClip()方法返回一个AudioClip对象,可以通过此装入声音文件,然后用AudioClip提供的方法播放。AudiClip getAudioClip(URL url) AudiClip getAudioClip(URL url,String name) 参数url为声音文件所在的地址,name为声音文件名称。
  • 558. 558AudioClip接口方法 主要有三个方法:play() 、loop()、 stop()。 void play() 开始播放,从头开始。 void loop() 反复循环播放。 void stop() 停止播放。
  • 559. 559例 程序名称Sample3_5.java import java.awt.*; import java.applet.*; public class Sample3_5 extends Applet{ public void paint(Graphics g){ g.setColor(Color.blue); g.drawString("在applet直接播放声音", 50, 60 ); g.setColor(Color.red); g.fill3DRect(40,90,410,40,true); play(getCodeBase(), "sound/yahoo1.au"); play(getCodeBase(), "sound/music.au"); } }
  • 560. 560相关的HTML文件Sample3_5.html
    这是利用Applet的play()播放声音的例程
  • 561. 561例 演示用AudioClip接口方式播放一段音乐。
  • 562. 第六章、图形用户界面(GUI)Swing 和 JFC562
  • 563. 6.1 Swing与JFC1.JFCJFC是Java Foundation Classes 的简称,它封装了一组用于建立图形化的用户界面(GUI)和增加Java应用富图形功能和交互性的特性,定义的这些特性如下:Swing GUI Components Pluggable Look-and-Feel Support Accessibility API Java 2D API Internationalization563
  • 564. javax.accessibility javax.swing.plaf javax.swing.text javax.swing javax.swing.plaf.basic javax.swing.text.html javax.swing.border javax.swing.plaf.metal javax.swing.text.html.parser javax.swing.colorchooser javax.swing.plaf.multi javax.swing.text.rtf javax.swing.event javax.swing.plaf.synth javax.swing.tree javax.swing.filechooser javax.swing.table javax.swing.undo2.Swing相关的包564
  • 565. 第六章、图形用户界面(GUI)GUI界面构成565
  • 566. 6.2 GUI界面构成1.GUI界面的组成在Java程序中图形界面由容器、布局、组件和事件处理构成。 容器 - 用于容纳或包含组件和作为子容器的其他容器。 布局 - 用于安排容器内组件排列顺序和样式,是组件的布局管理器。 组件 - 用于输入和输出的界面构件,是一个具有图形表示能力的对象,可在屏幕上显示,并可与用户进行交互。典型图形用户界面中的按钮、复选框和滚动条。 事件 – 由硬件和组件发出的 566
  • 567. 组件1组件2组件3组件4事件处理1事件处理2事件处理n567
  • 568. 2.容器和布局容器(Container) 容器(Container)是一种可以容纳其他组件的组件,AWT中的所有组件都是从Container类派生而来。 在GUI中容器有顶层容器和非顶层容器,顶层容器包含有: Frame、JFrame、JDialog、Applet和JApplet。 非顶层容器有: Panel、JPanel 、Canvas等。568
  • 569. GUI程序界面构成:FrameMenuBarContent Pane569
  • 570. GUI程序界面对象:570
  • 571. 布局管理(Layout Managers ) 当把组件放入容器时,容器通过布局对象来管理组件,控制组件的位置和尺寸。通常每个容器或组件均有相关的布局对象,也可以根据需要创建合适组件的布局对象。GUI用到的布局有: BorderLayout BoxLayout CardLayout FlowLayout GridBagLayout GridLayout GroupLayout SpringLayout 571
  • 572. 常用布局的排列样式:572
  • 573. 573
  • 574. 3.创建GUI界面在Java中,图形界面由容器、布局和组件(又称构件)组成。各种组件在布局的管理下自动排列,通过事件处理使得用户可以控制组件,进行交互。我们构建一个图形用户界面,一般有下面几个步骤: 设计界面样式。 分解界面成几个符合GUI容器、布局的基本样式。 选择容器以及与之相对应的布局管理。 创建组件,加入组件到相应容器。 注册事件处理对象,实现事件处理。 这只是普遍的做法,具体实施时还要求能够对AWT相关类有所了解,并且结合所设计界面的操作要求。下图表示一个GUI界面的组成:574
  • 575. 容器(Panel)布局(FlowLayout)组件(Button)Open 事件处理Close 事件处理OpenClose575
  • 576. 界面创建过程:…… Panel pane; Button open,close; pane = new Panel(); open = new Button(“Open”); open.addActionListener( new Open事件处理() ); pane.add(open); close = new Button(“Close”); close.addActionListener( new Close事件处理() ); pane.add(close); ……576
  • 577. 4.使用顶层容器在awt中顶层容器只有Frame,Swing提供了顶层JFrame、JDialog和JApplet。顶层容器: 显示在屏幕上。 每个GUI构件可以被容纳在其中。 顶层容器有一个内容(Content)Pane. 可为顶层容器增加菜单。 下图表示一个顶层容器的构成。577
  • 578. FrameMenuBarContent Pane578
  • 579. (1) 添加构件到内容(Content)Pane调用方法getContentPane()返回内容pane,即: 顶层容器.getContentPane() 默认的内容pane是一个继承于JComponent的中介容器,它的默认布局管理是BorderLayout 。 调用内容pane的add()添加构件。 如果需要,可以调用setContentPane(contentPane)重新设置内容pane。 579
  • 580. class GuiClass extends JFrame{ …… public GuiClass() { …… JPanel pane=(JPanel)getContentPane(); …… pane.add(构件对象); …… pane.add(构件对象 , BorderLayout.Xxxx); …… } …… }580
  • 581. (2) 添加菜单栏(Menu Bar)在理论上,所有顶层容器可以持有一个菜单栏。然而,在实践中经常出现在菜单栏只有Frame和Applet。添加一个菜单栏到一个顶级的容器,需要: 创造一个JMenuBar对象, 然后调用setJMenuBar()方法。其代码:…… JMenuBar menuBar = new JMenuBar(); …… 顶层容器.setJMenuBar(menuBar); ……581
  • 582. (3) 设置容器布局在使用容器时需要关心容器的布局管理,JPanels和内容pane都会有默认的布局管理。 JPanel对象初始化后用一个FlowLayout布局管理。 内容pane使用BorderLayout布局。 如果你不喜欢Panel和内容pane默认的布局管理,可以自由地更改它。改变默认布局管理可以调用容器的方法: 容器对象.setLayout( 布局对象 );例如, Container contentPane = frame.getContentPane(); contentPane.setLayout(new FlowLayout()); JPanel panel = new JPanel(new BorderLayout()); 582
  • 583. 第六章、图形用户界面(GUI)事件监听与处理583
  • 584. 6.3 事件监听与处理1.事件处理模型AWT 1.0 版中的事件处理模型基于继承。为了让程序俘获并处理GUI事件,必须扩展GUI组件并覆盖 action()或handleEvent()方法。从这些方法中返回“true”将消耗该事件,以使不再进一步处理它;否则,将在 GUI 层次中继续向上传播该事件,直到该事件被消耗或到达层次的根。 从JDK1.1开始引入了代理模型或者称为“委托事件模型”,事件类型封装在以 java.util.EventObject 为根的类层次中。通过调用监听器的方法,并在定义所产生事件类型的事件子类的实例中,将事件从“源”对象传播到“监听器”对象。584
  • 585. 2.事件层次 (1).低级事件 低级事件代表屏幕上可视化组件的低级输入或窗口系统事件。AWT 定义的低级事件类有:AWTEvent ,ComponentEvent,InputEvent ,KeyEvent 等。(2). 语义事件 语义事件是在较高层次定义的,用于封装用户接口组件模型的语义。AWT 定义的语义事件有:ActionEvent 指示发生了组件定义的动作的语义事件。事件被传递给每一个 ActionListener 对象,这些对象是使用组件的 addActionListener 方法注册的,用以接收这类事件。585
  • 586. ItemEvent 指示项被选定或取消选定的语义事件。此高级事件是在用户已选定项或取消选定项时由 ItemSelectable 对象(如 List)生成的。该事件被传递到每个 ItemListener 对象,这些对象都已使用组件的 addItemListener 方法注册接收此类事件。 TextEvent 指示对象文本已改变的语义事件。当某个对象(如 TextComponent)的文本改变时,该对象将生成此高级别事件。该事件被传递给每一个使用组件的 addTextListener 方法注册以接收这种事件的 TextListener 对象。 586
  • 587. 3.事件监听器低级事件,事件源是一个可视化组件类,事件紧密地绑定到屏幕上的实际组件。低级监听器在下列组件上定义: java.awt.Component类 addComponentListener(ComponentListener l) addFocusListener(FocusListener l) addKeyListener(KeyListener l) addMouseListener(MouseListener l) addMouseMotionListener(MouseMotionListener l) java.awt.Container 类 addContainerListener(ContainerListener l) java.awt.Dialog 类 addWindowListener(WindowListener l) java.awt.Frame 类 addWindowListener(WindowListener l)587
  • 588. 语义事件,源通常是代表语义模型的高级接口(并且这个高级接口通常由使用该模型的组件‘实现’)。下面是为 AWT 组件定义的语义监听器: java.awt.Button组件 addActionListener(ActionListener l) java.awt.Choice组件 addItemListener(ItemListener l) java.awt.Checkbox组件 addItemListener(ItemListener l) java.awt.CheckboxMenuItem组件 addItemListener(ItemListener l) java.awt.List组件 addActionListener(ActionListener l) addItemListener(ItemListener l)588
  • 589. java.awt.MenuItem 组件 addActionListener(ActionListener l) java.awt.Scrollbar组件 addAdjustmentListener(AdjustmentListener l) java.awt.TextArea 组件 addTextListener(TextListener l) java.awt.TextField 组件 addActionListener(ActionListener l) addTextListener(TextListener l)589
  • 590. 4.监听处理事件 在GUI应用中响应处理组件的事件时,把一个类或对象注册成该事件的监听者,并为关心的事件建立监听器,让事件监听者实现规定的EventListener接口方法。对于事件监听者来说,实现EventListener接口可以通过两种方式实现:选择自己实现EventListener接口方法,或者创建辅助类实现接口。辅助类可以是一个命名内部类,或者一个匿名内部类,或者一个外部类。 通过适配器的子类实现。注册成该事件的监听者是通过事件源(组件)提供一套用于注册事件特定监听器的setListener或addListener方法实现。 590
  • 591. 下面几个示例代码介绍各种不同的事件处理方式。 (1)使用应用实现EventListener接口方法。class myFrame extends JFrame implements ActionListener{ JButton button; …… // 注册myFrame为ActionEvent监听者 button. addActionListener(this); …… // 实现ActionListener监听器接口 public void actionPerformed(ActionEvent e) { …… } …… }591
  • 592. (2) 使用匿名内嵌类实现EventListener接口方法。class myFrame extends JFrame{ JButton button; …… // 注册myFrame为ActionEvent监听者 button. addActionListener(new ActionListener(){ // 实现ActionListener监听器接口 public void actionPerformed(ActionEvent e){ …… } }); …… }592
  • 593. (3) 使用命名内嵌类实现EventListener接口方法。public class MyFrame extends JFrame { JButton button; buttonAction listene; …… public MyFrame() { …… // 注册listener为ActionEvent监听者 listener=new buttonAction (); button. addActionListener(listener); } // 内嵌类实现EventListener接口方法 class buttonAction implements ActionListener { public void actionPerformed(ActionEvent e){ …… } } } 593
  • 594. (4) 使用外部辅助类实现EventListener接口方法。public class MyFrame extends JFrame{ JButton button; buttonAction listene; …… public MyFrame() { …… // 注册listener为ActionEvent监听者 listener=new buttonAction (); button. addActionListener(listener); } } // 实现EventListener接口的外部类 class buttonAction implements ActionListener { public void actionPerformed(ActionEvent e){ …… } } 594
  • 595. (5) 使用适配器类实现事件处理。class MyFrame extends JFrame { …… public MyFrame() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); …… } }595
  • 596. 5.类 AWTEvent 所有 AWT 事件的根事件类。 直接子类 :ActionEvent AdjustmentEvent AncestorEvent ComponentEvent HierarchyEvent InputMethodEvent InternalFrameEvent InvocationEvent ItemEvent TextEvent 596
  • 597. 第六章、图形用户界面(GUI)基本GUI构件597
  • 598. 6.4 基本GUI构件1.按钮(Button/JButton) 按钮(Button)是一种功能类似于开关图形组件,在Java中它必须有标签。当用户单击按钮时,产生一个ACTIN_EVENT事件,该事件以按钮标签为标识。构造方法 Button() 创建一个无标签按钮。 Button(String label) 创建一个标签为label按钮。598
  • 599. 主要方法 void addActionListener(ActionListener l) 添加指定事件监听器从按钮接收Action事件。当用户鼠标在它上面 按下或释放时引起这个事件,如果参数l时null无动Action事件响应。 参数 l - action事件监听 。 String getActionCommand() 返回被按钮引发的动作事件命令名称,如果命令名为null,返回标签。 String getLabel() 返回标签。 void setActionCommand(String command) 设置被按钮引发的动作事件命令名称。 void setLabel(String label) 设置被按钮引发的动作事件命令名称。 599
  • 600. 2.标签(Label/JLabel) 标签是静态的组件,仅仅作为文本字符串用于显示。它不产生动作事件。构造方法 Label() Label(String text) Label(String text, int alignment) 参数 label 标签文字串 alignment 对齐方式,可用下面的值: CENTER 居中 LEFT 左对齐 RIGHT 右对齐600
  • 601. 主要方法 int getAlignment() 返回对齐方式。 String getText() 返回标签文字串 void setAlignment(int alignment) 设置对齐方式。 void setText(String text) 设置标签文字串601
  • 602. 3.检查框(Checkbox) Checkbox是一个能够用于反映"on" (true) 和 "off" (false)状态的组件。单击一个checkbox改变它的状态从"on" 到 "off", 或从"off" 到"on." 构造方法 Checkbox() Checkbox(String label) Checkbox(String label, boolean state) Checkbox(String label, boolean state, CheckboxGroup group) Checkbox(String label, CheckboxGroup group, boolean state) 创建检查框。 参数 label 检查框标签;state 初始状态,on=true off=false group 如果需要多个检查框协同工作,需创建一个CheckboxGroup对象,在创建Checkbox时加入该对象。 602
  • 603. 主要方法 void addItemListener(ItemListener l) 添加事件监听器。 CheckboxGroup getCheckboxGroup() 返回CheckboxGroup对象。 String getLabel() 返回标签。 Object[] getSelectedObjects() 返回包含标签的数组,如果Checkbox未被选择,返回null。 boolean getState() 返回Checkbox状态true或false。 void setCheckboxGroup(CheckboxGroup g) 设置CheckboxGroup对象。 void setLabel(String label) 设置标签 void setState(boolean state) 设置状态。 603
  • 604. 4.选择框(Choice) Choice是一个弹出式菜单组件。当前选择被做为菜单标题显示。构造方法 Choice() 创建一个选择框。 主要方法 void add(String item) 增加一项到菜单。 void addItem(String item) 增加一项到选择框。 void addItemListener(ItemListener l) 添加一个事件监听器,用于从Choice菜单接收项目。 String getItem(int index) 返回由指定序号的项目。 604
  • 605. int getItemCount() 返回项目数目。 int getSelectedIndex() 返回被选中的当前项目号。 String getSelectedItem() 返回被选中的当前项目。 Object[] getSelectedObjects() 返回当前选择的所有项目到数组。 void insert(String item, int index) 在由index指定的位置插入一项。 void remove(int position) 删除一项。 void remove(String item) 删除一项。 void removeAll() 删除所有项。 void select(int pos) 选择一项。 void select(String str) 选择一项。 605
  • 606. int getItemCount() 返回项目数目。 int getSelectedIndex() 返回被选中的当前项目号。 String getSelectedItem() 返回被选中的当前项目。 Object[] getSelectedObjects() 返回当前选择的所有项目到数组。 void insert(String item, int index) 在由index指定的位置插入一项。 606
  • 607. void remove(int position) 删除一项。 void remove(String item) 删除一项。 void removeAll() 删除所有项。 void select(int pos) 选择一项。 void select(String str) 选择一项。 607
  • 608. 5.列表框(List) List产生一个一次可以选择一个或多个值的列表。构造方法 List() List(int rows) List(int rows, boolean multipleMode) 创建List对象。 参数:rows 可以显示出的行数。 multipleMode 多行选择标志,true-允许多选 false-单选 主要方法 void add(String item) 在行末增加一项。 void add(String item, int index) 在列表指定的位置增加一项。 void addActionListener(ActionListener l) 增加动作事件监听器。 608
  • 609. void addItemListener(ItemListener l) 增加项目事件监听器。 String getItem(int index) 返回指定序号的项目。 int getItemCount() 返回列表中项目数。 String[] getItems() 返回所有项目到一个String数组。 int getRows() 返回列表中显示的项目数。 int getSelectedIndex() 返回当前被选择的项目序号。609
  • 610. int[] getSelectedIndexes() 返回当前所有被选择的项目序号。 String getSelectedItem() 返回当前被选择的项目。 String[] getSelectedItems() 返回当前所有被选择的项目。 Object[] getSelectedObjects() 返回当前所有被选择的项目。 int getVisibleIndex() boolean isIndexSelected(int index) 测试指定项目是否被选择。 boolean isMultipleMode() 测试是否为多选择方式。 610
  • 611. 6.文本输入(TextField和TextArea) TextField是一个单行输入的文本输入组件。而TextArea是允许多行输入的文本输入组件。 构造方法 TextField() TextField(int columns) TextField(String text) TextField(String text, int columns) 创建TextField对象。 参数 int columns 输入行的宽度(字符数) String text 初始字符串 TextArea() TextArea(int rows, int columns) TextArea(String text) 611
  • 612. TextArea(String text, int rows, int columns) TextArea(String text, int rows, int columns, int scrollbars) 创建TextArea对象。 参数 int rows 输入区域的行数。 int columns 输入区域的列数。 String text 输入区域初始内容。 int scrollbars 输入域滚动条的状态: SCROLLBARS_BOTH 垂直与水平滚动条。 SCROLLBARS_VERTICAL_ONLY 垂直滚动条。 SCROLLBARS_HORIZONTAL_ONLY 水平滚动条。 SCROLLBARS_NONE。无滚动条。 612
  • 613. 主要方法 (1)TextField方法. void addActionListener(ActionListener l) boolean echoCharIsSet() 指出组件中是否设置有一个可回显的字符。 int getColumns() 返回文本域的列数。 char getEchoChar() 返回回显字符串。 void removeActionListener(ActionListener l) void setColumns(int columns) 设置文本域的列数。 void setEchoChar(char c) 设置回显字符串。 void setText(String t) 设置一个文本串在组件内。 613
  • 614. (2)TextField方法. void append(String str) 追加文本。 int getColumns() 返回输入区域列数。 int getRows() 返回输入区域行数。 void insert(String str, int pos) 插入文本在指定的位置。 void replaceRange(String str, int start, int end) 用指定的文本替换文本输入区的指定区域。 void setColumns(int columns) 设置输入区域列数。 void setRows(int rows) 设置输入区域行数。614
  • 615. 第七章 线程 615
  • 616. Java程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务。很多人可能对于多任务有一定的了解,即计算机在看上去几乎同一时间内运行多个程序。而多线程的程序则在更接近于机器本身的基础上发展这一思想,这就是说单个程序内部也可以在同一时刻进行多种运算。 很多程序语言需要利用外部的线程软件包来实现多线程,而Java则内在支持多线程,它的所有类都是在多线程的思想下定义的。Java利用线程使整个系统成为异步。 616
  • 617. 7.1 线程 什么是线程? 是程序中单独顺序的流控制 。 线程本身不能运行,它只能用于程序中。线程就是程序中单独顺序的流控制。 617
  • 618. 1 线程体 线程的所有活动都是通过线程体run()方法来实现的。在一个线程被建立并初始化以后,Java的运行时系统就自动调用run()方法,正是通过run()方法才使得建立线程的目的得以实现。 通常,run()方法是一个循环,有两种方法可以构造用户自己的run()方法。 Java的线程是通过Java的软件包Java.lang中定义的类Thread来实现的。为了更方便准确地使用线程,我们首先必须了解线程各方面的内容及其与Java运行时系统的关系。例如怎样构造线程体、线程的生命期、运行时系统如何安排线程等。下面我们分别进行介绍。 618
  • 619. 2 线程的状态 在一个线程的生命周期中,它总处于某一种状态中。线程的状态表示了线程正在进行的活动以及在这段时间内线程能完成的任务。图表示了一个Java线程所具有的不同状态及各状态间进行转换所需调用的方法。 619
  • 620. (1)、创建状态(new Thread)  下面的声明创建了一个新的线程,使它处于创建状态。 Thread myThread = new MyThreadClass( ); 由于没有启动这一线程,所以当一个线程处于创建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。处于这种状态时只能启动或终止该线程,调用除这两种以外的其它方法都会失败并且会引起非法状态处理。 (2)、可运行状态( Runnable )  Thread myThread = new MyThreadClass( ); myThread.start( ); 其中start()方法产生了运行这个线程所需的系统资源,安排其运行,并调用线程体—run()方法,这样就使得该线程处于可运行( Runnable )状态。 620
  • 621. (3)、不可运行状态(Not Runnable)  当下面四种情况发生时,线程就进入不可运行状态: 调用了sleep()方法; 调用了suspend()方法; 为等候一个条件变量,线程调用wait()方法; 输入输出流中发生线程阻塞。  例如: Thread myThread = new MyThreadClass(); myThread.start(); try{ myThread.sleep(10000); } catch (InterruptedException e){ }621
  • 622. (4)、死亡状态(Dead)  线程的终止一般可通过两种方法实现:自然撤消或是被停止。自然撤消是指从线程的run()方法正常退出。如下例中的while语句循环100次后将退出: public void run() { int i = 0; while (i < 100) { i++; System.out.println("i = " + i); } } 也就是说当run()方法结束后,该线程就自然撤消。 622
  • 623. 7.2 构造线程体创建新执行线程有两种方法。 一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。 另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。 Java的线程是通过Java的软件包Java.lang中定义的类Thread和Runnable 接口来实现的。类Thread类的主要成员见下所列。 623
  • 624. 构造方法:创建Thread对象。 Thread() Thread(Runnable target) Thread(Runnable target, String name) Thread(String name) Thread(ThreadGroup group, Runnable target) Thread(ThreadGroup group, Runnable target, String name) target是实现Runnable接口的类的对象。name是线程的名字。每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。624
  • 625. 方法: void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 void stop() 强迫线程停止执行。已过时。 void suspend() 挂起线程。已过时。 625
  • 626. Runnable 接口的主要成员见下所列。 void run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。 Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。 626
  • 627. 1 通过继承构造线程  我们可以建立一个类Thread的子类,通过继承类Thread并覆盖其run()方法和其他方法来构造线程体。例5.1 class TwoThreadsTest { public static void main (String args[]) { new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); } }  类 TwoThreadsTest的main()方法中构造了两个SimpleThread类的线程,一个称为"Jamaica",另一个为 " Fiji ",并在构造后马上就调用了start()方法来启动这两个线程。627
  • 628. class SimpleThread extends Thread { public SimpleThread(String str) { super(str); } public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getName()); try { sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + getName()); } }628
  • 629. 2 通过接口构造线程体  通过建立一个实现了Runnable接口的对象,并以它作为线程的目标对象也可以构造线程体。例5.2 public class Clock extends java.applet.Applet implements Runnable { Thread clockThread; public void start() { if (clockThread == null) { clockThread = new Thread(this, "Clock"); clockThread.start(); } }629
  • 630. public void run() { while (clockThread != null) { repaint(); try { clockThread.sleep(1000); } catch (InterruptedException e){ } } } public void paint(Graphics g) { Date now = new Date(); g.drawString(now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(), 5, 10); } public void stop() { clockThread.stop(); clockThread = null; } } 630
  • 631. 这是一个时钟Applet,它显示当前时间并逐秒进行更新。该Applet利用Runnable接口为其线程提供run()方法。类Clock由类Applet扩展而得,但同时它需要一个线程来实现时间的更新显示。由于Java中不支持多重继承,所以它不能再继承类Thread,而是利用了Runnable接口。 首先,在start()方法中构造了一个名为clockThread的线程 并调用Thread.start()方法来启动这一线程,即在Java运行时建立系统的线程关系。下面这句建立了一个新的线程: clockThread = new Thread(this, "Clock"); 其中this是Thread 构造方法中的第一个自变量,作为该线程的目标对象,它必须实现Runnable接口。在这种构造方法下,线程clockThread就以它的可运行的目标对象中的run()方法为其run()方法,在本例中,这个目标对象就是Clock Applet。构造方法中的第二个变量为线程名。 631
  • 632. 7.3 同步与共享 经常有一些同时运行的线程需要共享数据,例如一个线程向文件写数据,而同时另一个线程从同一文件中读取数据,因此就必须考虑其它线程的状态与行为,这时就需要实现同步来得到预期结果。 Java用监视器的手段来完成线程的同步。监视器将受保护的资源外面加了一把锁,而这把锁只有一把钥匙,每一个线程只有在得到这把钥匙之后才可以对被保护的资源执行操作,这线程执行操作完成之后,再将这把钥匙交给下一个即将对所要保护资源进行操作的线程,而其他的线程只能等待,直到拿到这把钥匙。632
  • 633. 1 关键字synchronizedJava中用关键字synchronized来完成监视器(monitor)这一角色。用这个关键字声明的方法,系统将为其设置一个内部标记。这个标志起着信号量的作用,每当调用该方法时,Java运行时系统都将进行检查,以确认此标志的状态。确认相应代码是否已被调用。如果没有,系统把标志授予调用对象,方法可以运行。运行结束后标志被释放。在此标志未被释放前,任何其他对象通常不能调用此方法。synchronized代码声明方式: synchronized 方法类型 方法名称(参数){ 需要进行同步的代码 }633
  • 634. synchronized除了用在方法声明,同样也可以用在代码段。带synchronized代码段的声明方法: synchronized(被锁定的对象){ 需要进行同步的代码 } 634
  • 635. public class CubbyHole { private int contents; private boolean available = false; public synchronized int get(int who) { while (available == false) { try { wait(); } catch (InterruptedException e) { } } available = false; notifyAll(); return contents; } }635
  • 636. 2 wait()和notify()方法 wait()和notify()方法用于线程的同步。可以在synchronized方法中调用。 wait() 方法将导致当前线程处于等待状态,直到其他线程调用此对象的 notify() 方法 或 notifyAll() 方法唤醒此线程,否则线程将永远等待下去。此方法只应由作为此对象监视器的所有者的线程来调用。 636
  • 637. notify() 方法唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者: 通过执行此对象的同步 (Sychronized) 实例方法。 通过执行在此对象上进行同步的 synchronized 语句的正文。 对于 Class 类型的对象,可以通过执行该类的同步静态方法。 637
  • 638. 7.4 示例 模拟台球台上移动的弹子,当弹子碰到边缘时会被弹回。如下图所示。点击“开始”弹子开始移动638
  • 639. Table.java源程序分析:639
  • 640. 640
  • 641. 第八章  数据库技术641
  • 642. 8.1、JDBC介绍 JDBC是一种用于执行SQL语句的 Java API(常被认为是代表 “Java 数据库连接(Java Database Connectivity)”)。它由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的 API,使他们能够用纯 Java API 来编写数据库应用程序。642
  • 643. 8.2、JDBC数据库访问模型 JDBC API 既支持数据库访问的两层模型,同时也支持三层模型。 1.两层模型 Java Applet 或应用程序将直接与数据库进行对话。这将需要一个 JDBC 驱动程序来与所访问的特定数据库管理系统进行通讯。用户的 SQL 语句被送往数据库中,而其结果将被送回给用户。数据库可以位于另一台计算机上,用户通过网络连接到上面,即所谓的“客户机/服务器”配置,其中用户的计算机为客户机,提供数据库的计算机为服务器。网络可以是 Intranet,也可以是Internet。模型结构见下图:643
  • 644. DBMS-proprietary protocolDBMSJDBCJava 应用Client machine (客户)Database server (数据库服务)JDBC 二层模型 644
  • 645. 2.三层模型 命令先是被发送到服务的“中间层”。 然后由它将 SQL 语句发送给数据库。 数据库对 SQL 语句进行处理并将结果送回到中间层,中间层再将结果送回给用户。 MIS 主管们都发现三层模型很吸引人,因为可用中间层来控制对公司数据的访问和可作的的更新的种类。中间层的另一个好处是,用户可以利用易于使用的高级 API,而中间层将把它转换为相应的低级调用。最后,许多情况下三层结构可提供一些性能上的好处。 645
  • 646. DBMS-proprietary protocolClient machine (客户)Database server (数据库服务)DBMSJDBC应用程序服务器Web 浏览器 (Applet/HTML)HTTP,RMI或CORBA调用服务器(商务逻辑)JDBC 三层模型 646
  • 647. 8.3、Java数据库操作的基本步骤与使用其他数据库系统类似,利用JDBC访问数据库系统需要经过连接数据库、查询/更新数据和关闭数据库连接。1.安装数据库驱动程序:DriverManager类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。加载Driver类,然后自动在 DriverManager中注册的方式有两种: 647
  • 648. 方法1: 通过调用方法Class.forName。这将显式地加载驱动程序类。由于这与外部设置无关,因此推荐使用这种加载驱动程序的方法。 Class.forName(“数据库驱动类名"); 以下代码加载类 acme.db.Driver: Class.forName("acme.db.Driver"); Class.forName(“数据库驱动类名");648
  • 649. 方法2: 通过将驱动程序添加到java.lang.System的属性 jdbc.drivers 中。这是一个由 DriverManager 类加载的驱动程序类名的列表,由冒号分隔:初始化 DriverManager 类时,它搜索系统属性 jdbc.drivers,如果用户已输入了一个或多个驱动程序,则 DriverManager 类将试图加载它们。jdbc.drivers=数据库驱动类名1:数据库驱动类名2;649
  • 650. 以下代码说明程序员如何在 ~/.hotjava/properties 中输入三个驱动程序类(启动时,HotJava 将把它加载到系统属性列表中):注意: 加载驱动程序的第二种方法需要持久的预设环境。如果对这一点不能保证,则调用方法 Class.forName 显式地加载每个驱动程序就显得更为安全。这也是引入特定驱动程序的方法,因为一旦 DriverManager 类被初始化,它将不再检查 jdbc.drivers 属性列表。 jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver; 650
  • 651. 加载 Driver 类并在 DriverManager 类中注册后,它们即可用来与数据库建立连接。当调用 DriverManager.getConnection()方法发出连接请求时,DriverManager 将检查每个驱动程序,查看它是否可以建立连接。2.建立连接 :public static Connection getConnection(String url) throws SQLException651
  • 652. getConnection建立到给定数据库 URL 的连接。DriverManager 试图从已注册的驱动程序集中选择一个适当的驱动程序。 参数: url - 数据库 url,格式 jdbc:subprotocol:subname 返回: URL的数据库连接对象Connection 652
  • 653. 例如 JDBC-ODBC 桥驱动程序建立连接所需所有步骤的示例: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:fred"; Connection con ; con=DriverManager.getConnection(url,"userID", "passwd");653
  • 654. 3.创建 Statement 对象:建立了到特定数据库的连接之后,就可用该连接发送SQL语句。Statement对象用Connection的方法 createStatement 创建,Statement 对象用于将 SQL 语句发送到数据库中。 Statement createStatement() throws SQLException 返回: 一个新的默认 Statement 对象654
  • 655. 创建一个 Statement 对象来将 SQL 语句发送到数据库。没有参数的 SQL 语句通常使用 Statement 对象执行。 如果多次执行相同的SQL语句,使用 PreparedStatement 对象可能更有效。 使用返回的 Statement 对象创建的结果集在默认情况下类型为 TYPE_FORWARD_ONLY,并带有 CONCUR_READ_ONLY 并发级别。 655
  • 656. Statement对象方法executeQuery,执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。 4.查询数据内容ResultSet executeQuery(String sql) throws SQLException 参数:sql - 要发送给数据库的 SQL 语句,通常为静 态 SQL SELECT语句。 返回:包含给定查询所生成数据的 ResultSet 对象; 永远不能为 null 656
  • 657. 5.使用ResultSet对象ResultSet表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于第一行之前。next方法将指针移动到下一行;因为该方法在 ResultSet 对象中没有下一行时返回false,所以可以在 while 循环中使用它来迭代结果集。 默认的 ResultSet 对象不可更新,仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更新的 ResultSet 对象。657
  • 658. ResultSet 包含符合 SQL 语句中条件的所有行,并且它通过一套 get 方法(这些 get 方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next 方法用于移动到 ResultSet 中的下一行,使下一行成为当前行。 658
  • 659. ResultSet对象包含有对记录集每行的列获取当前行中某列值方法。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。方法的格式: 列数据类型 getXxx(列名或列号 ) 其中Xxx表示列数据类型。用作 getXXX 方法的输入的列名不区分大小写。列是从左至右编号的,并且从列 1 开始。下面列出几个常用方法: 列数据类型 getXxx(列名或列号 )659
  • 660. boolean getBoolean(int columnIndex) boolean getBoolean(String columnName) byte getByte(int columnIndex) byte getByte(String columnName) double getDouble(int columnIndex) double getDouble(String columnName) String getString(int columnIndex) String getString(String columnName) float getFloat(int columnIndex) float getFloat(String columnName) 660
  • 661. int getInt(int columnIndex) int getInt(String columnName) long getLong(int columnIndex) long getLong(String columnName) 其中, columnIndex - 列号 columnName - 列名 661
  • 662. int executeUpdate(String sql) throws SQLException 执行给定SQL语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句。 参数: sql - SQL INSERT、UPDATE 或 DELETE 语句。 返回: INSERT、UPDATE 或 DELETE 语句的行计数;或者 0,表示不返回任何内容的 SQL 语句 6.更新数据库内容662
  • 663. 7.关闭:用户不必关闭ResultSet。当产生它的 Statement 关闭、重新执行或用于从多结果序列中获取下一个结果时,该 ResultSet 将被 Statement 自动关闭。如果要关闭可以调用close()方法。 关闭 Statement 对象调用close()方法。 关闭 Connection调用close()方法,663
  • 664. 8.4、应用实例SimpleSelect Music Musicview664
  • 665. 665
  • 666. 第九章  Java网络技术666
  • 667. 9.1、网络类库 在Java中有关网络程序设计的实现由java.net包封装的网络API类库提供,这个类库大致分为两部分: 低级API 前者用于处理,地址(也就是网络标识符,如 IP 地址。),套接字(也就是基本双向数据通信机制)和接口(用于描述网络接口)。 和高级API。 而后者用于处理URI(表示统一资源标识符。),URL(表示统一资源定位符。)和连接(表示到 URL 所指向资源的连接。)。 667
  • 668. 1.地址 在整个java.net API 中,地址或者用作主机标识符或者用作套接字端点标识符。 InetAddress 类是表示IP(Internet 协议)地址的抽象,它拥有两个子类:用于 IPv4 地址的Inet4Address和用于IPv6 地址的 Inet6Address。但是,在大多数情况下,不必直接处理子类,因为 InetAddress 抽象应该覆盖大多数必需的功能。668
  • 669. 2.套接字 套接字是在网络上建立机器之间的通信链接的方法。java.net 包提供4种套接字: Socket:TCP客户端API,通常用于将连接到远程主机。 ServerSocket:TCP服务器API,通常接受源于客户端套接字的连接。 DatagramSocket:UDP端点API,用于发送和接收。 MulticastSocket:DatagramSocket的子类,在处理多播组时使用。 套接字的发送和接收操作需要借助 InputStream 和 OutputStream 来完成,这两者是通过Socket的getInputStream方法和getOutputStream方法获取的。669
  • 670. 3.高级 API java.net 包中的许多类可以提供更加高级的抽象,允许方便地访问网络上的资源。这些类为: URI:表示在RFC2396中指定的统一资料标识符的类。它只是一个标识符,不直接提供访问资源的方法。 URL:表示统一资源定位符的类,它是访问资源的方法。 URLConnection:根据URL创建的,是用于访问URL所指向资源的通信链接。此抽象类将大多数工作委托给底层协议处理程序,如 http 或 ftp。 670
  • 671. HttpURLConnection:URLConnection的子类,提供一些特定于 HTTP 协议的附加功能。 建议的用法是使用URI指定资源,然后在访问资源时将其转换为 URL。从该 URL 可以获取 URLConnection 以进行良好控制,也可以直接获取 InputStream。 671
  • 672. 9.2、套接字(Socket) 套接字(socket)是在网络上建立机器之间的通信链接的方法。它是一种网络编程模型下,进程间通信链路的端点。 一个socket包括两个流:一个输入流和一个输出流。如果一个进程要通过网络向另一个进程发送数据,只需简单地写入与socket相关联的输出流。一个进程通过从与socket相关联的输入流读来读取另一个进程所写的数据。建立网络连接之后,使用与socket相关联的流和使用其他流是非常相似的。 672
  • 673. 1.Java网络模型Socket模型 673
  • 674. 服务器分配一个端口号。如果客户请求一个连接,服务器使用accept()方法打开socket连接。 客户在host的port端口建立连接。 服务器和客户使用InputStream和OutputStream进行通信。TCP/IP系统中的端口号是一个16位的数字,它的范围是0~65535。实际上,小于1024的端口号保留给预定义的服务,而且除非要和那些服务之一进行通信(例如telnet,SMTP邮件和ftp等),否则你不应该使用它们。客户和服务器必须事先约定所使用的端口。如果系统两部分所使用的端口不一致,那就不能进行通信。674
  • 675. 2.ServerSocket类此类实现服务器套接字。服务器套接字等待请求通过网络传入。创建ServerSocket对象就可以实现Socket服务,用于监听本地或远程客户程序通过公共端口的连接请求。当接到一个客户请求后, ServerSocket对象就会创建一个Socket对象,至于如何响应客户请求发回数据给客户,则由Socket对象处理。ServerSocket类的主要方法如下:675
  • 676. ServerSocket(int port) 创建绑定到特定端口的服务器套接字。参数port 是端口号,若为 0 则表示任何空闲的端口。输入连接指示(对连接的请求)的最大队列长度被设置为 50。如果队列满时收到连接指示,则拒绝该连接。如果打开套接字发生I/O错误,则会抛出IOException 异 676
  • 677. Socket accept() 侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。当有连接请求时创建新套接字对象Socket。 void close() 关闭此套接字。 677
  • 678. 用指定端口创建ServerSocket对象。 调用对象的accept方法监听客户连接请求。 接受客户请求并创建一个Socket类对象。 用Socket对象接收用户数据或发送数据给客户。 关闭Socket对象。 关闭ServerSocket对象.用ServerSocket类创建服务Socket包含下面内容:678
  • 679. 679
  • 680. 3.Socket类此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器之间的通信端点。这个类的主要方法包括:Socket(String host,int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。host主机名,或者为 null,表示回送地址。 如果无法确定主机的 IP 地址抛出UnknownHostException异常;如果创建套接字时发生 I/O 错误抛出IOException异常。680
  • 681. InputStream getInputStream() 返回socket的输入流对象InputStream,用于读取发送个当前Socket的数据。 OutputStream getOutputStream() 返回socket的输出流对象OutputStream,用于发送数据。 void close() 关闭此套接字。 InetAddress getInetAddress() 返回套接字连接的地址。 此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。681
  • 682. Socket类用于处理客户端程序和客户请求处理,在处理请求时需要四步操作 :(1) 创建一个Socket对象来连接到服务器上。即: Socket connection = new Socket(address, port); address——主机名称或服务器的url地址 port—指定请求连接的主机端口号682
  • 683. (2).使用Socket对象的getInputStream方法获得socket的InputStream对象引用;使用Socket对象的getOutputStream方法获得socket的OutputStream对象引用。InputStream用于从服务方读取数据,通常调用read方法按字节或字节数组读入数据。OutputStream对象的Write方法用于向服务器发送数据,一次可以发送单个字节或一组数据。 (3).使用InputStream和OutputStream进行客户端与服务端的数据通讯。 (4).通讯结束,关闭Socket对象。683
  • 684. 684
  • 685. 9.3、对网上资源访问 类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。 一个URL可以唯一地设定一个WWW地址,Java网络类库提供的URL类,包含若干用以下载网络资源的方法。在这个类中URL类主要方法包括:(1)URL(String spec) 根据 String 表示形式创建 URL 对象。 685
  • 686. (2)Object getContent() 获得此 URL 的内容。 (3)InputStream openStream() 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。 686
  • 687. import java.net.*; import java.io.*; public class SimpleUrl { public static String fetch(String address){ try{ URL url=new URL(address); return (String)url.getContent(); }catch(IOException e){ e.printStackTrace(); } return ""; } public static void main(String []agrc){ System.out.println(SimpleUrl.fetch("http://www.baidu.com")); } }687
  • 688. 一.单实例模式(SINGLETON)对象创建型模式1.意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 2.适用性 在下面的情况下可以使用S i n g l e t o n模式 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。688
  • 689. 3.结构689
  • 690. 4.实现690