资源预览内容
第1页 / 共442页
第2页 / 共442页
第3页 / 共442页
第4页 / 共442页
第5页 / 共442页
第6页 / 共442页
第7页 / 共442页
第8页 / 共442页
第9页 / 共442页
第10页 / 共442页
亲,该文档总共442页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Java程序设计基础与实践 第第1章章Java环境的安装、配置与环境的安装、配置与运行运行本章导读Java是由SunMicrosystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。Java的诞生是对传统计算机模式的挑战,对计算机软件开发和软件产业都产生了深远的影响。Java一经推出就赢得了前所未有的成功,从2001年至今,Java语言一直是世界上应用最广泛的编程语言,因此现在有越来越多的工作者、学习者正努力进入Java领域或将要努力进入Java领域,因此,学习Java语言很有必要。“工欲善其事,必先利其器”,搭建开发环境是学习语言的第一步,环境好搭建后,熟悉开发环境及简单程序的解读就是学习语言的第二步了。本章要点Java简介Java的特点Java运行环境的安装与配置Java程序结构Java程序的运行机制和垃圾回收机制Java程序的编写、编译和运行1.1基础知识1.1.1Java简介美国硅谷有一句行话,每10年15年有一次轮回。最近的一次轮回就是从Java开始。Java的产生Sun的Java语言开发小组成立于1991年,其目的是开拓消费类电子产品市场,Sun内部人员把这个项目称为Green,Green小组的领导人是JamesGosling,是一位非常杰出的程序员。在研究开发过程中,Gosling深刻体会到消费类电子产品和工作站产品在开发哲学上的差异。消费类电子产品要求可靠性高、费用低、标准化、使用简单,用户并不关心CPU的型号,也不欣赏专用昂贵的RISC处理器。为了使整个系统与平台无关,Gosling首先从改写C+编译器着手。但是Gosling在改写过程中感到仅C+是无法满足需要的,于是在1991年6月份开始准备开发一个新的语言,那么给它起一个什么名字呢?Gosling回首向窗外望去,看见一棵老橡树,于是建一个目录叫Oak,这就是Java语言的前身。Java的产生Gosling在开始写Oak时,并不局限于扩充语言机制本身,更注重于语言所运行的软硬件环境。他要建立一个系统,这个系统运行于一个巨大的、分布的、异构的网格环境中,完成各电子设备之间的通信与协同工作。Gosling在设计中采用了虚机器码(VirtualMachineCode)方式,即Oak语言编译后产生的是虚拟机,虚拟机运行在一个解释器上,每一个操作系统均有一个解释器,这样一来,Oak就成了与平台无关语言。当Naughton加入该小组后,整个工作进展神速。经过17个月的奋战,整个系统胜利完成。它是由一个操作系统、一种语言(Java)、一个用户界面、一个新的硬件平台、三块专用芯片构成的。到了1994年,WWW已如火如荼地发展起来。Gosling意识到WWW需要一个中性的浏览器,它不依赖于任何硬件平台和软件平台,它应是一种实时性较高、可靠安全、有交互功能的浏览器。于是Gosling决定用Oak开发一个新的Web浏览器。Java的产生这项工作由Naughton和JonathanPayne负责,到1994年秋天,完成了WebRunner的开发工作。WebRunner是HotJava的前身,这个原型系统展示了Java可能带来的广阔市场前景。WebRunner改名为HotJava,并于1995年5月23日发表后,在产业界引起了巨大的轰动,Java的地位也随之而得到肯定。又经过一年的试用和改进,Java1.0版终于在1996年年初正式发表。Java语言在叫“Java”之前名为“Oak”,橡树。一门语言怎么起到了一棵树的名字?早先开发这门语言的Green小组成员,在为还在“孕期”中待产的新生语言起名时,看到了窗外的一棵橡树,就是这样一念的灵感和联想,把一门新生语言的小名落实了。可惜这个绿意的名字最终被放弃,因为在用Oak去注册商标时,发现这个名已被注册他用,于是Sun的精英们喝着咖啡编排新名,杯里的热咖啡冒着香气,顺着香气思维游荡到盛产咖啡的爪哇岛,爪哇!Java由此命名。Java的发展Sun继Green项目后又经过了几年的研究,终于在1995年5月23日在SunWorld95上正式发布Java和HotJava浏览器。在同年,有很多公司先后获得了Java许可证,如Netscape在1995年8月,Oracle在1995年10月分别获得了Java许可证。Sun在1995年发布第一个Java版本后,于1996年1月宣布成立新的业务部门JavaSoft部,这个部分主要负责开发、销售并支持基于Java技术的产品,由AlanBaratz先生任总裁。在1995年Sun虽然推出了Java,但这只是一种语言,而要想开发复杂的应用程序,必须要有一个的强大的开发库支持还行。因此,Sun在1996年1月23日发布了JDK1.0。这个版本包括了两部分:运行环境(即JRE)和开发环境(即JDK)。在运行环境中包括了核心API、集成API、用户界面API、发布技术和Java虚拟机(JVM)五个部分。而开发环境还包括了编译Java程序的编译器(即javac)。在JDK1.0时代,JDK除了AWT(一种用于开发图形用户界面的API)外,其它的库并不完整。Java的发展Sun在推出JDK1.0后,紧跟着,Sun在1997年2月18日发布了JDK1.1。JDK1.1相对于JDK1.0最大的改进就是为JVM增加了JIT(即时编译)编译器。JIT和传统的编译器不同,传统的编译器是编译一条,运行完后再将其扔掉,而JIT会将经常用到的指令保存在内容中,在下次调用时就不需要再编译了。这样JDK在效率上有了非常大的提升。Sun在推出JDK1.1后,接着又推出了数个JDK1.x版本。1998年是Java开始迅猛发展的一年。在这一年中Sun发布了JSP/Servlet、EJB规范以及将Java分成了J2EE、J2SE和J2ME。标志着Java已经吹响了向企业、桌面和移动3个领域进军的号角。到1998年,Java已经走过了3个年头。从JDK1.0到JDK1.1.8。JDK1.x经过了9个小版本的发展,已经初具规模。至此,它已经走出了摇篮,可以去独闯世界了。Java的发展在1998年12月4日。Sun发布了Java的历史上最重要的一个JDK版本:JDK1.2。这个版本标志着Java已经进入Java2时代。这个时期也是Java飞速发展的时期。在Java2时代Sun对Java进行了很多革命性的变化,而这些革命性的变化一直沿用到现在,对Java的发展形成了深远的影响。JDK1.2自从被分成了J2EE、J2SE和J2ME三大块,得到了市场的强烈反响。不仅如此,JDK1.2还对它的API分成了核心API、可选API和特殊API三大类。从JDK1.2开始,Sun以平均2年一个版本的速度推出新的JDK。在2000年5月8日。Sun对JDK1.2进行了重大升级。推出了JDK1.3。Sun在JDK1.3中同样进行了大量的改进,主要表现在一些类库上(如数学运算、新的TimerAPI等)、在JNDI接口方面增加了一些DNS的支持、增加了JNI的支持,这使得Java可以访问本地资源、支持XML以及使用新的Hotspot虚拟机代替了传统的虚拟机。Java的发展2002年2月13日Sun发布了JDK历史上最为成熟的版本JDK1.4。在进入21世纪以来,曾经在.NET平台和Java平台之间发生了一次声势浩大的孰优孰劣的论战,Java的主要问题就是性能。因此,这次Sun将主要精力放到了Java的性能上。在JDK1.4中,Sun放言要对Hotspot虚拟机的锁机制进行了改进,使JDK1.4的性能有了质的飞跃。同时由于Compaq、Fujitsu、SAS、Symbian、IBM等公司的参与,使JDK1.4成为发展最快的一个JDK版本。到JDK1.4为止,我们已经可以使用Java实现大多数的应用了。在2004年10月,Sun发布了我们期待已久的版本JDK1.5,同时,Sun将JDK1.5改名为J2SE5.0。和JDK1.4不同,JDK1.4的主题是性能,而J2SE5.0的主题是易用。Sun之所以将版本号1.5改为5.0,就是预示着J2SE5.0较以前的J2SE版本有着很大的改过。Java的发展到2006年底Sun又再接再厉地推出了J2SE6.0的测试版,并在2007年初推出它的正式版。正象J2SE6.0的开发代号“野马(Mustang)”一样,我们已经隐约听到了野马的嘶鸣。据Sun发言人称,J2SE6.0不仅在性能、易用性方面得到了前所未有的提高,而且还提供了如脚本、全新的API(Swing和AWT等API已经被更新)的支持。而且J2SE6.0是专为Vista而设计的,它在Vista上将会拥有更好的性能。在推出J2SE6.0的同时,J2SE7.0项目也已经启动。在Java发展的十几年的时间里,经历了无数的风风雨雨。现在Java已经成为一种相当成熟的语言了。在这10年的发展中,Java平台吸引了数百万的开发者,在网络计算遍及全球的今天,更是有20亿台设备使用了Java技术。2009年4月20日,Oracle(甲骨文)宣布收购Sun。Java的意义的意义软件4A目标要求软件能达到任何人在任何地方在任何时间对任何电子设备都能应用。这样能满足软件平台上互相操作,具有可伸缩性和重要性并可即插即用等分布式计算模式的需求。基于构建开发方法的崛起,引出了CORBA国际标准软件体系结构和多层应用体系框架。在此基础上形成了Java.2平台和.NET平台两大派系,推动了整个IT业的发展。Java的意义的意义对软件产业和工业企业都产生了深远的影响,软件从以开发为中心转到了以服务为中心。中间提供商,构件提供商,服务器软件以及咨询服务商出现。企业必须重塑自我,B2B的电子商务将带动整个新经济市场,使企业获得新的价值,新的增长,新的商机,新的管理。对软件开发带来了新的革命,重视使用第三方构件集成,利用平台的基础设施服务,实现开发各个阶段的重要技术,重视开发团队的组织和文化理念,协作,创作,责任,诚信是人才的基本素质。1.1.2Java语言特点Java语言是简单的Java语言是面向对象的Java语言是分布式的Java语言是健壮的Java语言是安全的Java语言是体系结构中立的1.1.2Java语言特点Java语言是可移植的Java语言是解释型的Java是高性能的Java语言是多线程的Java语言是动态的1.1.3Java运行环境的安装与配置JDK是Java开发工具包(JavaDevelopmentKit)的缩写。它是一种用于构建在Java平台上发布的应用程序、applet和组件的开发环境。JDK是一切Java应用程序的基础,所有的Java应用程序是构建在这个之上的。它是一组API,也可以说是一些JavaClass。要成为一个Java程序员,JDK是必不可少的最基本的工具。JDK的下载与安装的下载与安装机器要求机器要求Java对机器运行要求不高。下面给出的是基于Windows平台的机器要求。硬件要求:CPUPII以上,64M内存,100M硬盘空间即可。软件要求:Windows98/Me/XP/NT/2000,IE5以上。JDK的下载与安装下载下载 JDK为了建立基于JDK的Java运行环境,需要先下载Sun的免费JDK软件包。JDK包含了一整套开发工具,其中包含对编程最有用的是Java编译器、Applet查看器和Java解释器。在浏览器中输入http:/java.sun.com/javase/downloads/index.jsp,可看到JDK下载主页面。下载下载JDK在JavaPlatform中选择JDK6Update18,点击“DownloadJDK”按钮,即可进入JDK1.6下载页面。单击Download按钮,即可进入jdk-6u18-windows-i586.exe的下载页面。此时点击jdk-6u18-windows-i586.exe,即可下载。安装安装JDK双击下载的“jdk-6u18-windows-i586.exe”软件包,出现安装向导窗口。等待一段时间,会自动出现安装协议窗口。单击“接受”按钮,出现安装路径设置窗口。缺省安装路径为“C:ProgramFilesJavajdk1.6.0_18”,可以单击“更改”按钮改变安装路径,这里不做修改,单击“下一步”按钮,出现JDK安装界面。安装过程中会出现JRE的安装界面。单击“更改”按钮可以改变安装路径,由于安装JDK时已经安装了JRE,所以该项是可选的,如果不安装,点击“取消”按钮。单击“下一步”按钮即安装JRE。安装过程大约持续几分钟,出现安装结束窗口,单击“完成”按钮即可完成JDK的安装。JDK文件浏览文件浏览安装成功后,可以浏览安装路径下“Javajdk1.6.0_18”中的文件和子目录结构,其中,bin文件夹中包含编译器(javac.exe)、解释器(javac.exe)、Applet查看器(appletviewer.exe)等可执行文件,Demo文件夹中包含一些源代码的程序示例,感兴趣的同学可自行查看。Java运行环境的配置方法运行环境的配置方法绝对路径绝对路径绝对路径方法中无需配置JAVA_HOME。CLASSPATH中输入“.;C:ProgramFilesJavajdk1.6.0_18jrelibrt.jar”。PATH中输入“C:ProgramFilesJavajdk1.6.0_18bin”。其中,“C:ProgramFilesJavajdk1.6.0_18”为JDK安装路径。Java运行环境的配置方法运行环境的配置方法相对路径方法相对路径方法首先定义一新的环境系统变量JAVA_HOME,令JAVA_HOME=“C:ProgramFilesJavajdk1.6.0_18”。CLASSPATH中用%JAVA_HOME%取代“C:ProgramFilesJavajdk1.6.0_18”,CLASSPATH中输入“.;%JAVA_HOME%jrelibrt.jar;”。同样,PATH中用%JAVA_HOME%取代“C:ProgramFilesJavajdk1.6.0_18”,PATH中输入“%JAVA_HOME%bin;”。Java运行环境的配置方法运行环境的配置方法批命令方法批命令方法编辑一文件,具体文件命令如下:echooffIFEXIST%1binjava.exe(rem如输入正确的Java2JDK安装目录,开始设置环境变量setxJAVA_HOME%1setxpath%path%;%JAVA_HOME%binsetxclasspath%classpath%.;setxclasspath%classpath%;%JAVA_HOME%jrelibrt.jar;echoonechoJava2JDK环境参数设置完毕,正常退出。)Java运行环境的配置方法运行环境的配置方法ELSE(IF%1=(rem如没有提供安装目录,提示之后退出echoonecho没有提供Java2JDK的安装目录,不做任何设置,现在退出环境变量设置。)ELSE(rem如果提供非空的安装目录但没有binjava.exe,则指定的目录为错误的目录echoonecho非法的Java2JDK的安装目录,不做任何设置,现在退出环境变量设置。)Java运行环境的配置方法运行环境的配置方法命令行方法命令行方法命令行方法为每次重新启动MS-DOS编译和运行Java程序时设置,在提示符下键入如下命令:SETPATH=C:ProgramFilesJavajdk1.6.0_18bin;SETCLASSPATH=.;C:ProgramFilesJavajdk1.6.0_18jrelibrt.jar;Java运行环境的具体配置Path和和Classpath的配置的配置在桌面“我的电脑”图标上单击右键,选择“属性”菜单,将出现系统特性设置窗口,在“高级”选项卡中单击“环境变量”按钮。将出现“环境变量”设置窗口,在“系统变量”列表框中选择“Path”,然后单击“编辑”按钮,在出现的“编辑系统变量”对话框中,在“变量值”栏的命令最前面添加“C:ProgramFilesJavajdk1.6.0_18bin;”命令,用同样方法设置环境变量“classpath”,其值为“.;C:ProgramFilesJavajdk1.6.0_18jrelibrt.jar;”命令,由于一般系统安装时没有classpath这个环境变量,所以要新建该环境变量,设置完成后,单击“开始”/“所有程序”/“附件”/“命令提示符”打开DOS窗口,在命令提示符下输入“java”或“javac”,回车后,如果出现其用法参数提示信息,则表明安装配置成功Java运行环境的具体配置设置设置DOS起始位置起始位置为了在打开DOS窗口时可以直接进入Java程序的开发路径下,下面以WindowsXP/2000为例说明设置过程。首先建立一个存放Java源程序的路径和文件夹,如将实践中建立的Java源程序都存放在为“e:javabook”文件夹中。单击“开始”/“所有程序”/“附件”/“命令提示符”,选中“命令提示符”选项单击鼠标右键,在出现的下拉菜单中选择“属性”菜单,打开“命令提示符属性”对话框,在“命令提示符属性”对话框中选择“快捷方式”选项页,在“起始位置”栏输入“e:javabook”,单击“确定”按钮即可。进行了上面的设置后,打开DOS窗口时将直接进入“e:javabook”路径下。1.1.4Java程序结构一个Java应用包含一个或多个Java源文件,每个Java源文件只能包含如下内容(空格或注释除外):0个或1个包声明语句(PackageStatement)0个或多个包引入语句(ImportStatement)0个或多个类的声明(ClassDeclaration)0个或多个接口声明(InterfaceDeclaration)每个Java源文件可包含多个类或接口的定义,但是至多只有一个类或者接口是public的,而且Java源文件必须以其中public类型的类的名字命名。Java程序主要分为两类:Java应用程序(application):单独的窗口应用,一定要有包含main()方法的主程序。Java小程序(applet):这类程序嵌入在WWW的页面中,作为页面的组成部分被下载,并且能运行在实现Java虚拟机的web浏览器中,它没有main()方法。Java程序程序publicclassHellopublicstaticvoidmain(Stringargs)System.out.println(Hello,java!);注意Java程序应注意:代码中区分大小写。在这个代码中定义public类的名字是要和保存的文件名相同。JavaApplet程序程序importjava.applet.Applet;importjava.awt.Graphics;publicclassHelloWorldAppletextendsAppletpublicvoidpaint(Graphicsg)g.drawString(HelloWorld!,0,50);注意讲解到这里,似乎有一个误解,认为只有在JavaApplet程序中会使用import语句,而在Java应用程序中不要使用import语句。千万不要有这个误解,Java应用程序中也会经常使用import语句,只不过前面的例子是十分简单的应用程序,所以没有用到import语句,但Java中所有类都是Object类的子类,不用import语句显式引入。而JavaApplet程序是一定要使用这个语句的,应为至少需要包括与Applet有关的类。1.1.5Java程序的运行机制和垃圾回收机制Java程序的运行机制程序的运行机制Java是一种特殊的高级语言,它既具有编译型语言的特征,又具有解释型语言的特征。Java程序需要先要经过编译,再经过解释两个步骤才能运行。Java语言编写的程序需要经过编译,而编译所生成的并不是特定的平台机器码,只是一个与平台(操作系统)无关的字节码文件。当然这种字节码不能被系统执行,必须使用Java解释器(JVM,JavaVirtualMachine,也称为Java虚拟机,)来执行。JVM是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的,Java虚拟机有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统,JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。1.1.5Java程序的运行机制和垃圾回收机制Java的垃圾回收机制的垃圾回收机制内存是稀缺的资源,Java语言提供了垃圾收集机制。该机制用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象,从而可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。Java语言对内存的分配管理是通过JVM内部机制决定的,编程人员可以不关心其处理。虽然Java垃圾收集器处理了大多数内存管理问题,从而使编程变得更轻松了,但是编程人员还是可能犯错而导致出现内存问题,所以很多情况下高级编程人员自己管理内存,关于垃圾回收机制的问题请读者参阅相关参考资料。1.1.6Java程序的编写、编译、运行利用记事本编写、编译、运行利用记事本编写、编译、运行Java程序程序(a)编写Java源程序单击“开始”/“所有程序”/“附件”/记事本,打开记事本窗口,输入上面例子的Java源程序代码,保存路径为“E:javabook”,文件名为“Hello.java”。(b)编译Java程序使用Java编译器编译Java程序,具体命令如下:javacoptionssourcefilesfiles其中:javac是命令关键字,后面的为命令参数,参数可按任意次序排列。options命令行选项选项含义-g生成所有调试信息-g:none不生成任何调试信息-g:lines,vars,source只生成某些调试信息-nowarn不生成任何警告-verbose输出有关编译器正在执行的操作的消息-deprecation输出使用已过时的API的源位置-classpath指定查找用户类文件的位置-cp指定查找用户类文件的位置-sourcepath指定查找输入源文件的位置-bootclasspath覆盖引导类文件的位置-extdirs覆盖安装的扩展目录的位置-endorseddirs覆盖签名的标准路径的位置-d指定存放生成的类文件的位置-encoding指定源文件使用的字符编码-source提供与指定版本的源兼容性-target生成特定VM版本的类文件-version版本信息-help输出标准选项的提要-X输出非标准选项的提要-J直接将传递给运行时系统sourcefiles一个或多个要编译的源文件。files一个或多个对源文件进行列表的文件。如果源文件数量少,在命令行上列出文件名即可。如果源文件数量多,则将源文件名列在一个文件中,名称间用空格或回车行来进行分隔,然后在javac命令行中使用该列表文件名,文件名前冠以字符。例如,可以在名为sourcefiles的文件中列出所有源文件的名称。该文件可能形如:MyClass1.javaMyClass2.javaMyClass3.java然后可用下列命令运行编译器:e:javabookjavacsourcefiles注意:源代码文件名称必须含有.java后缀,类文件名称必须含有.class后缀,源文件和类文件都必须有识别该类的根名。例如,名为MyClass的类将写在名为MyClass.java的源文件中,并被编译为字节码类文件MyClass.class。缺省情况下,编译器将每个类文件与其源文件放在同一目录中,可用-d选项(请参阅后面的选项)指定其它目标目录。(c)运行Java程序Java使用Java解释器可将编译后的字节码文件Hello.class解释为本地计算机代码。命令如下:java-optionsclassargs.其中:class为字节码文件名。args是java程序执行时传递给main()方法的参数。options命令行选项选项含义-client选择“client”VM-server选择“server”VM-hotspot与“client”VM同义,默认情况的VM是client-cp指定查找用户类文件的位置-classpath指定查找用户类文件的位置-d=在虚拟机的系统属性中设置属性名/值对-verbose:class|gc|jni使详细输出变的可用-version打印产品版本然后退出-version:只运行指定版本-showversion打印产品版本后继续-?-help打印帮助信息-X打印非标准选项帮助使用EditPlus编辑、编译、运行Java程序(a)EditPlus编辑软件的下载和安装EditPlus编辑软件在网上有很多,在百度中输入“EditPlus下载”即可下载到该软件。EditPlus编辑软件的安装方法很简单,解压后自运行。使用EditPlus编辑、编译、运行Java程序(b)EditPlus用户工具的配置打开EditPlus编辑软件,单击“工具”/“配置用户工具”菜单,将打开的“参数设置”窗口,在打开的“参数选择”窗口中,单击“组名称”按钮,确定工具组的名称。单击“添加”按钮,从弹出的快捷菜单中选择“应用程序”命令。在“菜单文本”栏中输入“编译”文字,在“命令”栏中输入或通过文件夹选择javac.exe文件的路径,在“参数”栏选择“文件名称”,在“初始目录”栏输入Java程序所在的路径,选中“捕获输出”,单击“确定”按钮,注意,“命令”、“参数”和“初始目录”可以通过单击编辑栏后面的按钮在弹出的窗口中选择实现输入。同样的方法可以设置“运行”工具。使用EditPlus编辑、编译、运行Java程序(c)使用EditPlus编辑Java程序运行EditPlus,选择路径“E:javabook”,在左下角显示的文件中选中“Hello.java”程序,(d)使用EditPlus编译与运行Java程序单击“工具”/“编译”菜单,就开始对编写的程序进行编译处理,编译通过后,可在右下方窗口看到编译结果。如果程序有问题,可在右下方窗口中看到提示。编译成功后,单击“工具”/“运行”菜单,就开始运行刚通过编译的程序,可在右下方窗口看到运行结果。JavaApplet程序运行环境配置程序运行环境配置Java虚拟机与虚拟机与Internet浏览器的配置浏览器的配置为了在浏览器中正常浏览Java程序,需要检查两个方面的配置,一是要选择Java(TM)缺省浏览器,二是需要打开浏览器缺省配置下禁止的Java功能。(a)选择Java(TM)缺省浏览器Java(TM)软件中涉及Web交互的部分。它包括Java虚拟机和许多其它内容。有了它可以尽情享受Internet提供的最佳内容,包括游戏、体育、聊天、电子邮件、艺术、财务工具等等。在“控制面板”窗口双击图标,打开“Java(TM)Plug-in控制面板”对话框,选择“浏览器”选项,选中“MicrosoftInternetExplorer”复选框,此选择意味着选择“MicrosoftInternetExplorer”作为JavaApplet程序运行时缺省浏览器,单击“应用”按钮即可完成配置。JavaApplet程序运行环境配置程序运行环境配置(b)打开浏览器Java的功能打开一个IE窗口,在浏览器菜单栏单击“工具”/“Internet选项”命令,打开“Internet选项”对话框,选择“高级”选项卡,选取“Java(sun)”下的单选框,选取“MicrosoftVM”下的第一个选项“启用JavaJIT编译器”,选择“安全”选项卡,单击“自定义级别”按钮,将打开“安全设置”对话框,在“安全设置”对话框中把“MicrosoftVM”中的Java权限设置为“安全等级-中”;把“脚本”中的“JavaApplet程序脚本”设置为“启用”和“活动脚本”设置为“启用”。完成上面操作后,关闭浏览器再重新打开即可在浏览器中正常浏览JavaApplet程序。编写、运行编写、运行JavaApplet程序程序(a)编辑、编译JavaApplet源程序在EditPlus中,输入下面的程序代码,importjava.applet.Applet;importjava.awt.Graphics;publicclassHelloWorldAppletextendsAppletpublicvoidpaint(Graphicsg)g.drawString(HelloWorld!,0,50);然后存盘退出。单击“工具”/“编译”菜单,可在右下方窗口看到编译结果。编译成功后,将生成一个名为HelloWorldApplet.class的文件。编写、运行编写、运行JavaApplet程序程序(b)编辑包容JavaApplet程序的HTML文件由于JavaApplet程序是不能直接使用命令行来运行的,它们是嵌入到网页中的,要使用浏览器才能够运行,而浏览器是无法直接执行JavaApplet程序的。这时就必须通过HTML文件来告诉浏览器执行JavaApplet程序。在HTML文件中嵌入JavaApplet程序,应使用标志,这个标志包含几个参数:CODE:用来指出要嵌入的JavaApplet程序名称,是编译后的类文件名;WIDTH:用来指定JavaApplet程序的宽度;HEIGHT:用来指定JavaApplet程序的高度。注意,使用Java编程,Java源程序文件的名字应与类名一致,但包含小应用程序的HTML文件则无需与其一致,此处取名一致。编写、运行编写、运行JavaApplet程序程序(c)运行JavaApplet程序可以通过两种方法来运行JavaApplet程序:一种方法是使用支持Java的浏览器(如微软的IE、还用Netscape的Navigator),另一种方法是使用Java的小应用程序浏览器AppletViewer。第一种方法:首先打开IE浏览器,在地址栏上输入“E:javabookHelloWorldApplet.html”,将看到这个小应用程序的输出结果。第二种方法:利用AppletViewer命令,该命令主要用来测试Applet程序,使用该命令能够实时反映Applet程序的变化。使用AppletViewer命令不需要引入复杂的HTML代码,只需编写如下代码即可。在MS-DOS中输入“AppletViewerHelloWorldApplet.HTML”即可。Java程序设计基础与实践 第第2章章Java语言基础语言基础本章要点Java数据类型与运算符数据类型与运算符Java注释语句注释语句Java分支程序设计分支程序设计Java循环程序设计循环程序设计 Java数组数组Java字符串字符串数据类型与运算符数据类型数据类型Java语言是一种严格的语言是一种严格的“类型化类型化”语言。这意味着每个变量都必语言。这意味着每个变量都必须有一个声明好的数据类型。须有一个声明好的数据类型。Java语言提供了语言提供了8种基本数据类型种基本数据类型 :字节型字节型byte、短整型、短整型short、整型、整型int、长整型、长整型long、单精度浮点、单精度浮点型型float、双精度浮点型、双精度浮点型double、字符型、字符型char、逻辑类型、逻辑类型booleanJava是面向对象的程序设计语言,它为用户提供的复合数据类型包括数组、类和是面向对象的程序设计语言,它为用户提供的复合数据类型包括数组、类和接口等接口等 类型之间的转换类型之间的转换自动类型转换自动类型转换强制类型转换强制类型转换运算符运算符注释语句单行注释单行注释-/多行注释多行注释-“/* */”文档注释文档注释-“/* */”例如:在例如:在E:javabook中创建一个中创建一个First.java文件,其代码如下:文件,其代码如下:/*First.java*这是一个简单的这是一个简单的Java应用程序应用程序*/publicclassFirst/*public修饰的类为主类,类名和文件名保持一修饰的类为主类,类名和文件名保持一致致* */主类中要包含主类中要包含main()方法方法publicstaticvoidmain(Stringargs)/方法体方法体注释语句(续)使用使用javadoc命令可以获取文档注释信息,并且生成相命令可以获取文档注释信息,并且生成相应的应的API文档。文档。Javadoc命令用法如下:命令用法如下:javadoc选项选项软件包名称软件包名称源文件源文件file例如,在例如,在E:javabook中新建一文件夹中新建一文件夹Test,以,以First.java为例,将其生成的为例,将其生成的API文档存放在文档存放在Test文件文件夹中,命令如下:夹中,命令如下:javadocdTestFirst.java运行界面如图运行界面如图2.1所示。所示。 生成的生成的API文档如图文档如图2.2所示。其中所示。其中index.html是生成是生成的文档首页。的文档首页。注释语句(续)图2.1执行javadoc的运行界面注释语句(续)图2.2生成的API文档分支程序设计所谓分支语句就是对语句中不同条件的所谓分支语句就是对语句中不同条件的值进行判断,进而根据不同的条件执行值进行判断,进而根据不同的条件执行不同的语句。分支语句共有两种:不同的语句。分支语句共有两种:if语句语句和和switch语句语句 分支程序设计-if条件语句if语句的语法格式:语句的语法格式:if(条件(条件1)功能代码功能代码1;elseif(条件(条件2)功能代码功能代码2;elseif(条件(条件3)功能代码功能代码3;else功能代码功能代码;分支程序设计-switch语句switch语句的语法格式:语句的语法格式:switch(表达式表达式)case值值1:功能代码功能代码1;break;case值值2:功能代码功能代码2;break;default:功能代码功能代码1;break;循环程序设计循环就是反复执行一段代码,直到满足循环就是反复执行一段代码,直到满足结束条件。循环语句共有结束条件。循环语句共有while语句、语句、do-while语句和语句和for语句三种。语句三种。 循环程序设计-while语句while语句是语句是Java最基本的循环语句,其最基本的循环语句,其语法格式如下:语法格式如下:while(条件表达式条件表达式)/循环体循环体 循环程序设计-do-while循环do-while循环语句语法格式如下:循环语句语法格式如下:do/循环体循环体while(条件表达式条件表达式);循环程序设计-for循环for循环语句的通用格式如下:循环语句的通用格式如下:for(初始化语句初始化语句;循环条件循环条件;迭代语句迭代语句)语句序列语句序列三种循环语句while循环语句的特点是循环语句的特点是“先判断、后执先判断、后执行行”,循环体有可能执行,循环体有可能执行0次;次;do-while循环语句的特点是循环语句的特点是“先执行,后判断先执行,后判断”,循环体至少要执行,循环体至少要执行1次。次。while语句和语句和for语句在循环语句中都属于语句在循环语句中都属于“先判断再循环先判断再循环”的结构,在实际使用的结构,在实际使用时时while语句和语句和for语句之间可以很方便的语句之间可以很方便的进行替换。进行替换。循环程序设计-跳转语句continuecontinue语句可以终止一次循环。如果在某次循环体的执行中执语句可以终止一次循环。如果在某次循环体的执行中执行了行了continue语句,那么就不再执行本次循环中语句,那么就不再执行本次循环中continue语句后语句后面的语句,退出本次循环而直接进行下一次循环。面的语句,退出本次循环而直接进行下一次循环。breakbreak语句可以终止循环或其他控制结构。在语句可以终止循环或其他控制结构。在switch语句中,语句中,break语句可以用来终止一个语句序列;在循环语句中,语句可以用来终止一个语句序列;在循环语句中,break语语句可以用来退出一个循环。句可以用来退出一个循环。returnreturn语句可以从一个方法返回,并把控制权交给调用它的语句。语句可以从一个方法返回,并把控制权交给调用它的语句。return语句通常被放在方法的最后,用于退出当前方法并返回一语句通常被放在方法的最后,用于退出当前方法并返回一个变量或表达式的值。语法格式为:个变量或表达式的值。语法格式为:return变量或表达式的值变量或表达式的值;Java数组-一维数组一维数组的声明一维数组的声明 声明一维数组的格式为:声明一维数组的格式为:typearrayName;typearrayName;其中,类型其中,类型(type)可以为可以为Java中任意的数据类型,包括简单类型中任意的数据类型,包括简单类型和复合类型。和复合类型。 Java数组-一维数组一维数组的初始化一维数组的初始化 声明数组仅仅是给出数组名字和元素的数据类型,要声明数组仅仅是给出数组名字和元素的数据类型,要想使用数组还必须为它分配内存空间、赋初值。数组想使用数组还必须为它分配内存空间、赋初值。数组的初始化分为静态初始化和动态初始化两种。的初始化分为静态初始化和动态初始化两种。 静态初始化静态初始化 静态初始化是在定义数组的同时对数组元素进行初始静态初始化是在定义数组的同时对数组元素进行初始化,这种方式通常在数组元素个数较少的情况下使用化,这种方式通常在数组元素个数较少的情况下使用动态初始化动态初始化 使用动态初始化方法时,需要使用使用动态初始化方法时,需要使用new关键字来为数关键字来为数组分配空间。格式为:组分配空间。格式为:数组名字数组名字=new数组元素的类型数组元素的类型数组元素的个数数组元素的个数;Java数组-一维数组一维数组元素的引用一维数组元素的引用 一维数组元素的引用方式为:一维数组元素的引用方式为: arrayNameindex其中,其中,index为数组下标,它可以为整型常数或表达式,为数组下标,它可以为整型常数或表达式,下标从下标从0开始。开始。 Java数组-多维数组Java语言中,多维数组被看作数组的数组。下面以二语言中,多维数组被看作数组的数组。下面以二维数组为例介绍多维数组的定义、初始化和元素的引维数组为例介绍多维数组的定义、初始化和元素的引用。用。二维数组的声明二维数组的声明声明二维数组的格式为:声明二维数组的格式为:typearrayName;typearrayName;二维数组的初始化二维数组的初始化 二维数组的初始化同样分为静态初始化和动态初始化二维数组的初始化同样分为静态初始化和动态初始化两种。两种。静态初始化静态初始化 静态初始化是在定义数组的同时就为数组分配了内存静态初始化是在定义数组的同时就为数组分配了内存空间。空间。 Java数组-多维数组动态初始化动态初始化 对于二维数组的动态初始化,可以有两种方法。对于二维数组的动态初始化,可以有两种方法。直接为每一维分配空间直接为每一维分配空间格式如下:格式如下: arrayName=newtypelen1len2;上面的定义中配置了上面的定义中配置了len1行行len2列的二维数组对象列的二维数组对象Java数组-多维数组从最高维开始,分别为每一维分配空间从最高维开始,分别为每一维分配空间 inta;/声明一个二维整型数组声明一个二维整型数组a=newint2;/该二维数组由该二维数组由2个一维整型数组组个一维整型数组组成成a0=newint3;/第第1个一维数组由个一维数组由3个整数组成个整数组成a1=newint5;/第第2个一维数组由个一维数组由5个整数组成个整数组成二维数组元素的引用二维数组元素的引用 对二维数组中的每个元素,引用格式为:对二维数组中的每个元素,引用格式为:arrayNameindex1index2index1与与index2为下标,这个下标与一维数组一样,为下标,这个下标与一维数组一样,可以是常量、变量或表达式。可以是常量、变量或表达式。 Java数组-多维数组数组中常用属性和方法数组中常用属性和方法数组中常用属性数组中常用属性在数组的应用中经常用到数组的长度,表示一维数组在数组的应用中经常用到数组的长度,表示一维数组长度(即元素的个数)的格式为:数组长度(即元素的个数)的格式为:数组.length。lengh属性是数组中唯一的一个属性,属性是数组中唯一的一个属性,length属性也不属性也不存在于存在于API中,而是中,而是JVM自动给加上去的。自动给加上去的。Java数组-多维数组数组中常用方法数组中常用方法get(Objectarray,intindex)getBoolean(Objectarray,intindex)getByte(Objectarray,intindex)getChar(Objectarray,intindex)getDouble(Objectarray,intindex)getFloat(Objectarray,intindex)getInt(Objectarray,intindex)getLength(Objectarray)getLong(Objectarray,intindex)getShort(Objectarray,intindex)Java数组-多维数组数组中常用方法(续)数组中常用方法(续)set(Objectarray,intindex,Objectvalue)setBoolean(Objectarray,intindex,booleanz)setByte(Objectarray,intindex,byteb)setChar(Objectarray,intindex,charc)setDouble(Objectarray,intindex,doubled)setFloat(Objectarray,intindex,floatf)setInt(Objectarray,intindex,inti)setLong(Objectarray,intindex,longl)setShort(Objectarray,intindex,shorts)Java字符串字符串常量字符串常量字符串常量是用双引号括起来的一串字符。字符串常量是用双引号括起来的一串字符。 例如:例如:“HelloWorld!”字符串变量的声明字符串变量的声明Strings;字符串变量的创建字符串变量的创建Java语言中,把字符串变量作为对象来处理。语言中,把字符串变量作为对象来处理。Srting类有几种类有几种常见的方法可以将声明和创建一步完成:常见的方法可以将声明和创建一步完成:String();/初始化一个新创建的初始化一个新创建的String对象,它表示一个空字符对象,它表示一个空字符串串String(charchars);/用一个字符数组创建一个字符串对象用一个字符数组创建一个字符串对象String(charchars,intstartIndex,intnumChars);/*提取字提取字符数组符数组chars中中startIndex开始开始numChars个字符创建一个字符个字符创建一个字符串对象,串对象,*/String(Stringoriginal);/*初始化一个新创建的初始化一个新创建的String对象,表对象,表示一个与示一个与original相同的字符串即创建一个字符串副本相同的字符串即创建一个字符串副本* */字符串的常用方法字符串的常用方法length()charAt(intindex)indexOf(intch)lastIndexOf(inch)indexOf(Stringstr)lastIndexOf(Stringstr)indexOf(intch,intfromIndex)lastIndexOf(inch,intfromIndex)indexOf(Stringstr,intfromIndex)lastIndexOf(Stringstr,intfromIndex)getchars(intsrcbegin,intend,charbuf,intdstbegin)getBytes(intsrcbegin,intsrcEnd,bytebuf,intdstbegin)contat(Stringstr)replace(charoldChar,charnewChar)substring(intbeginIndex)substring(intbeginIndex,intendIndex)toLowerCase()toUpperCase()equals(ObjectanObject)equalsIgnoreCase(StringanotherString)另外,可以将数字串转换为整数和双精度数,方法格式如下:另外,可以将数字串转换为整数和双精度数,方法格式如下:Integer.parseInt(String);/将数字字符串转化为整型将数字字符串转化为整型Double.parseDouble(String);/将数字字符串转化为浮点型将数字字符串转化为浮点型本章小结Java语言是一种严格的语言是一种严格的“类型化类型化”语言。这意味着每个变量都必语言。这意味着每个变量都必须有一个声明好的数据类型。须有一个声明好的数据类型。Java语言提供了字节型、短整型、整语言提供了字节型、短整型、整型、长整型、单精度浮点型、双精度浮点型、字符型和逻辑类型型、长整型、单精度浮点型、双精度浮点型、字符型和逻辑类型8种种基本数据类型,语言和数组、类和接口等复合数据。基本数据类型,语言和数组、类和接口等复合数据。Java编程时有时需要进行数据类型转换,数据类型之间的转换有自编程时有时需要进行数据类型转换,数据类型之间的转换有自动类型转换和强制数据类型转换。要实现两种数据类型的自动转换,动类型转换和强制数据类型转换。要实现两种数据类型的自动转换,必须同时满足两个条件,一是两种数据类型彼此兼容,二是目标数必须同时满足两个条件,一是两种数据类型彼此兼容,二是目标数据类型的取值范围要大于源数据类型。能进行自动转换的数据类型据类型的取值范围要大于源数据类型。能进行自动转换的数据类型及转换规则如下:及转换规则如下:byte-short-char-int-long-float-double按照箭头所示方向,左侧的数据类型数据可以自动转换赋值给右侧按照箭头所示方向,左侧的数据类型数据可以自动转换赋值给右侧的数据类型变量,但反之,将右侧的数据类型数据赋值给左侧的数的数据类型变量,但反之,将右侧的数据类型数据赋值给左侧的数据类型变量必须经过强制类型转换。强制类型转换的转换格式为:据类型变量必须经过强制类型转换。强制类型转换的转换格式为:(目标类型)变量名或表达式(目标类型)变量名或表达式强制数据类型转换后可能会丢失一部分数据。强制数据类型转换后可能会丢失一部分数据。本章小结(续)Java语言提供了语言提供了()、!、+(正正)、-(负负)、+、-、* *、/、%、+(加加)-(减减)、=、instanceof、=、!=、&(按位与按位与)、|、&、|、?:、=、+=、-=、* *=、/=、%=、|=、=、=、=、=等运算符。等运算符。Java中可以采用单行注释、多行注释和生成帮助文中可以采用单行注释、多行注释和生成帮助文档的注释三种注释方式。档的注释三种注释方式。Java分支语句共有分支语句共有if语句和语句和switch语句两种。语句两种。Java循环语句共有循环语句共有while语句、语句、do-while语句和语句和for语句三种。语句三种。Java中支持中支持break语句、语句、continue语句和语句和return语句语句三种跳转语句。三种跳转语句。 本章小结(续)Java语言中,数组是一种最简单的复合数据类型。数组是有序数语言中,数组是一种最简单的复合数据类型。数组是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和下标来唯一地确定数组中的元素。一的数组名和下标来唯一地确定数组中的元素。数组的声明格式为:数组的声明格式为:数据类型数据类型数组名数组名维数维数;数据类型数据类型维数维数数组名数组名;声明数组仅仅是给出数组名字和元素的数据类型,要想使用数组还声明数组仅仅是给出数组名字和元素的数据类型,要想使用数组还必须为它分配内存空间、赋初值。数组的初始化分为静态初始化和必须为它分配内存空间、赋初值。数组的初始化分为静态初始化和动态初始化两种。静态初始化是在定义数组的同时对数组元素进行动态初始化两种。静态初始化是在定义数组的同时对数组元素进行初始化,这种方式通常在数组元素个数较少的情况下使用。动态初初始化,这种方式通常在数组元素个数较少的情况下使用。动态初始化方法是使用始化方法是使用new关键字来为数组分配空间。关键字来为数组分配空间。数组元素的引用方式为:数组元素的引用方式为: 数组名数组名维数索引维数索引Java字符串常量是用双引号括起来的一串字符。字符串常量是用双引号括起来的一串字符。Java语言中,把语言中,把String类型的字符串变量作为对象来处理。类型的字符串变量作为对象来处理。Java程序设计基础与实践 第3章类和对象面向对象的基本概念面向对象的基本概念Java语言的修饰符语言的修饰符Java类及类中变量与方法的分类和定义方法类及类中变量与方法的分类和定义方法Java对象的创建、使用和释放对象的创建、使用和释放3.1.1面向对象的编程的基本概念从程序设计的角度来看,面向对象的程序设计必须描从程序设计的角度来看,面向对象的程序设计必须描述对象及其相互之间的关系,系统中一切皆为对象,述对象及其相互之间的关系,系统中一切皆为对象,具体来说,每一个事物就是一个对象,对象所归属的具体来说,每一个事物就是一个对象,对象所归属的分类就是面向对象中重要概念类。分类就是面向对象中重要概念类。类与对象是不同但是又紧密相联的概念。对象是类的类与对象是不同但是又紧密相联的概念。对象是类的实例,是由类生成的,一个对象具有哪些特性和行为,实例,是由类生成的,一个对象具有哪些特性和行为,由类来决定。由类来决定。3.1.2Java语言的修饰符Java语言的修饰符分为访问控制符和非语言的修饰符分为访问控制符和非访问控制符两大类。访问控制符是一组访问控制符两大类。访问控制符是一组限定类、变量或方法是否可以被自身或限定类、变量或方法是否可以被自身或其他程序访问和调用的修饰符,非访问其他程序访问和调用的修饰符,非访问控制符是用于声明特殊类、变量和方法控制符是用于声明特殊类、变量和方法的修饰符。的修饰符。所属所属非访问控制符非访问控制符含义含义类类abstract抽象类修饰符抽象类修饰符,用用abstract修饰符修饰的类,被称为抽象类修饰符修饰的类,被称为抽象类final最终类修饰符最终类修饰符,当一个类不可能有子类时可用修饰符当一个类不可能有子类时可用修饰符final把它说明为最终类把它说明为最终类变量变量static静态修饰符静态修饰符,用用static修饰的成员变量属于类变量修饰的成员变量属于类变量final最终域修饰符最终域修饰符,用用final定义常量定义常量方法方法abstract抽象方法控制符抽象方法控制符,用修饰符用修饰符abstract修饰的方法称为抽象方法修饰的方法称为抽象方法static静态方法控制符静态方法控制符,用修饰符用修饰符static修饰的方法属于类方法修饰的方法属于类方法final最终方法控制符最终方法控制符, ,用修饰符用修饰符final修饰的方法称为最终方法修饰的方法称为最终方法nativenative本地方法控制本地方法控制符,符,用修饰符用修饰符native修饰的方法称为本地方法,声明可以被外部程序访问的方法修饰的方法称为本地方法,声明可以被外部程序访问的方法synchronized同步方法控制符同步方法控制符, ,该修饰符主要用于多线程共存的程序中的协调和同步该修饰符主要用于多线程共存的程序中的协调和同步表3.1Java语言主要类、变量和方法的非访问控制符基本含义表表3.2JavaJava语言访问控制符定义的访问权限表语言访问控制符定义的访问权限表同一类中同一类中同一包中同一包中不同包中的子类不同包中的子类不同包中的非子不同包中的非子类类适用范围适用范围publicyyyy类、变量、方法类、变量、方法protectedyyy变量、方法变量、方法缺省缺省yy类、变量、方法类、变量、方法privatey变量、方法变量、方法3.1.3类1.类的定义类的定义在在Java语言中,类定义的基本格式如下:语言中,类定义的基本格式如下:类修饰符类修饰符class类名类名extends父类名父类名implements接口列表接口列表/类声明类声明/类体类体2.变量变量变量的定义变量的定义变量的定义格式:变量的定义格式:变量修饰符变量修饰符类型说明符类型说明符 变量名变量名 =初始初始值值,变量名变量名=初始值初始值;变量的分类变量的分类成员变量和局部变量成员变量和局部变量在方法体外变量定义部分的变量称为成员变量,在方在方法体外变量定义部分的变量称为成员变量,在方法体内或方法参数中定义的变量称为局部变量。局部法体内或方法参数中定义的变量称为局部变量。局部变量的作用域为方法体内,成员变量的作用域为整个变量的作用域为方法体内,成员变量的作用域为整个类。类。Java中的成员变量在没有进行显示初始化的时候,系中的成员变量在没有进行显示初始化的时候,系统会自动赋予默认值;局部变量必须进行显示赋值操统会自动赋予默认值;局部变量必须进行显示赋值操作,否则无法通过编译器的编译。作,否则无法通过编译器的编译。例如:例如:class People /class People /定义类定义类 String name=John; /String name=John; /方法体外变量,为成员变量方法体外变量,为成员变量voidsetName(Stringname)/方法参数变量为局部变量方法参数变量为局部变量 System.out.println(System.out.println(采用采用this关键字获得的变量为:关键字获得的变量为:+this.name);/使用使用this访问成员变量访问成员变量 System.out.println(System.out.println(局部变量为:局部变量为:+name);/局部变量局部变量 StringgetName()returnname;/方法体内没有同名的局部变量,则访问方法体外面成方法体内没有同名的局部变量,则访问方法体外面成员变量员变量publicstaticvoidmain(Stringargs)Peoplep=newPeople();/创建创建People类对象类对象pp.setName(Mike);/为局部变量赋值为局部变量赋值 System.out.println(System.out.println(成员变量为:成员变量为:+p.getName();/调用方调用方法法实例变量、类变量、最终变量实例变量、类变量、最终变量实例变量实例变量对象是类的实例,类实例化后的变量称为实例变量。对象是类的实例,类实例化后的变量称为实例变量。类变量类变量类变量也称为静态变量,类变量使用类变量也称为静态变量,类变量使用static声明,系统声明,系统为每个类变量只分配一次存储空间,即所有的实例共为每个类变量只分配一次存储空间,即所有的实例共享一个存储空间。享一个存储空间。最终变量最终变量当在类中定义变量时,在其前面加上当在类中定义变量时,在其前面加上final关键字,表关键字,表示这个变量一旦被初始化便不可改变,对基本类型来示这个变量一旦被初始化便不可改变,对基本类型来说是其值不可变,而对于对象变量来说是其引用不可说是其值不可变,而对于对象变量来说是其引用不可变,称为最终变量,也称为变,称为最终变量,也称为final常量。常量。例如:例如:classPeople final String ID=0001; / final String ID=0001; /最终变量,不允许修改最终变量,不允许修改 String name; /String name; /实例变量实例变量 static String workspace=static String workspace=清华大学清华大学;/类变量,可以由类名直接访问类变量,可以由类名直接访问voidsetName(Stringname)this.name=name;StringgetName()returnname;publicstaticvoidmain(Stringargs)Peoplep=newPeople();p.setName(Mike); p.ID=0002; / p.ID=0002; /非法,最终变量不允许修改非法,最终变量不允许修改 System.out.println(System.out.println(对象名访问最终变量编号:对象名访问最终变量编号:+p.ID);System.out.println(System.out.println(类名访问最终变量编号:类名访问最终变量编号:+People.ID);/*非法,非法,最终变量不能由类名直接访问最终变量不能由类名直接访问*/ System.out.println( System.out.println(对象名访问实例变量姓名:对象名访问实例变量姓名:+p.getName(); System.out.println( System.out.println(类名访问实例变量姓名:类名访问实例变量姓名:+People.getName();/*非法,非法,实例变量不能由类名直接访问,类名访问类变量实例变量不能由类名直接访问,类名访问类变量*/System.out.println(System.out.println(类名访问类变量工作单位:类名访问类变量工作单位:+People.workspace);/类名访问类类名访问类变量变量System.out.println(System.out.println(对象名访问类变量工作单位:对象名访问类变量工作单位:+p.workspace);/对象名访问类变量对象名访问类变量3.方法方法方法的定义方法的定义在在Java语言中,方法只能作为类的成员,又称为成员语言中,方法只能作为类的成员,又称为成员方法,其定义基本格式如下:方法,其定义基本格式如下:方法修饰符方法修饰符返回值的类型返回值的类型 成员方法名成员方法名(形式参数表形式参数表)throw异常表异常表/方法声明方法声明/局部变量声明部分局部变量声明部分/执行语句部分执行语句部分基本类型作为参数基本类型作为参数当方法的参数是基本类型(包括整型、浮点、布尔型当方法的参数是基本类型(包括整型、浮点、布尔型和字符型等)时,它是通过传值方式进行调用的,即和字符型等)时,它是通过传值方式进行调用的,即只是将实参的值的拷贝传递给方法,在方法内对形参只是将实参的值的拷贝传递给方法,在方法内对形参进行操作,其操作对象是实参的拷贝,对实参不能造进行操作,其操作对象是实参的拷贝,对实参不能造成影响。成影响。例如:例如:classPeopleStringid,name;voidsetName(Stringname)/字符型参数字符型参数this.name=name;StringgetName()returnname;StringgetInfo(Stringid,Stringname) / /字符型参数字符型参数id=0002;name=John; String str= String str=形参编号:形参编号:+id+,+形参姓名:形参姓名:+name;returnstr;publicstaticvoidmain(Stringargs)Peoplep=newPeople(); / /定义的实参定义的实参p.setName(Mike);p.id=0001; System.out.println(p.getInfo(p.id,p.getName(); / System.out.println(p.getInfo(p.id,p.getName(); /输出形参结果输出形参结果 System.out.println(System.out.println(实参编号:实参编号:+p.id+,+实参姓名:实参姓名:+p.getName();/输出输出实参结果实参结果运行结果:运行结果:形参编号:形参编号:0002,形参姓名:形参姓名:John实参编号:实参编号:0001,实参姓名:实参姓名:Mike复合类型作为参数复合类型作为参数复合类型参数的传值属于复合类型参数的传值属于“传址传址”方式,引用是对象方式,引用是对象在内存中的地址,方法调用时,将实参的地址传递给在内存中的地址,方法调用时,将实参的地址传递给形参,使得形参与实参共享同一内存地址,在方法内形参,使得形参与实参共享同一内存地址,在方法内对形参进行操作即等于对实参进行相同的操作,在方对形参进行操作即等于对实参进行相同的操作,在方法结束返回后,形参同样被释放,实参的内容是对形法结束返回后,形参同样被释放,实参的内容是对形参操作的结果。参操作的结果。例如:例如:classPeopleStringid,name;voidsetName(Stringname)this.name=name;StringgetName()returnname;StringgetInfo(Peopleq)q.id=0002;q.name=John; String str= String str=形参编号:形参编号:+q.id+,+形参姓名:形参姓名:+q.name;returnstr;publicstaticvoidmain(Stringargs)Peoplep=newPeople(); / /定义实参定义实参p.setName(Mike);p.id=0001; System.out.println(p.getInfo(p); / System.out.println(p.getInfo(p); /输出形参结果输出形参结果 System.out.println(System.out.println(实参编号:实参编号:+p.id+,+实参姓名:实参姓名:+p.getName();/输出实输出实参结果参结果运行结果:运行结果:形参编号:形参编号:0002,形参姓名:形参姓名:John实参编号:实参编号:0002,实参姓名:实参姓名:John方法的分类方法的分类实例方法实例方法类实例化的方法称为实例方法,没有特殊的非访问控类实例化的方法称为实例方法,没有特殊的非访问控制符标识。制符标识。类方法类方法类方法也称为静态方法,使用类方法也称为静态方法,使用static声明,就像类变量声明,就像类变量一样,类的所有实例对象共享同一个类方法。一样,类的所有实例对象共享同一个类方法。例如:例如:classPeople final String ID=0001; / final String ID=0001; /最终变量,不允许修改最终变量,不允许修改 String name; /String name; /实例变量实例变量 static String workspace=static String workspace=清华大学清华大学;/类变量,可以由类名直接访问类变量,可以由类名直接访问voidsetName(Stringname)this.name=name;StringgetName()returnname;staticStringgetworkspace()returnworkspace;publicstaticvoidmain(Stringargs)Peoplep=newPeople();p.setName(Mike); System.out.println( System.out.println(类名类名.方法名方式访问实例方法实例变量姓名:方法名方式访问实例方法实例变量姓名:+People.getName();/*非法,实例方法不能采用类名非法,实例方法不能采用类名.方法名的方式访问方法名的方式访问*/ System.out.println( System.out.println(对象名对象名.方法名方式访问实例方法实例变量姓名:方法名方式访问实例方法实例变量姓名:+p.getName(); System.out.println( System.out.println(类名类名.方法名方式访问类变量工作单位:方法名方式访问类变量工作单位:+People.getworkspace();System.out.println(System.out.println(对象名对象名.方法名方式访问类变量工作单位:方法名方式访问类变量工作单位:+p.getworkspace();最终方法最终方法如果一个类不允许其子类重写某个方法,如果一个类不允许其子类重写某个方法,则可以把这个方法使用则可以把这个方法使用final修饰,这个修饰,这个方法称为最终方法。方法称为最终方法。例如:例如:/*/*设计毕业生类作为最终类,获取毕业前最后考试成绩设计毕业生类作为最终类,获取毕业前最后考试成绩 */final class Graduates /final class Graduates /定义最终类,不允许被继承定义最终类,不允许被继承Stringname,id;intage,score;publicGraduates(Stringname,Stringid,intage)this.name=name;this.id=id;this.age=age; / /定义最终方法,不允许被覆盖定义最终方法,不允许被覆盖 final void setScore(int score) /final void setScore(int score) /设置最终成绩设置最终成绩this.score=score; final int getScore() / final int getScore() /获取最终成绩获取最终成绩returnscore;publicstaticvoidmain(Stringargs) Graduates g=new Graduates( Graduates g=new Graduates(王明王明,23330,22);g.setScore(65);System.out.println(g.getScore();抽象方法抽象方法用关键字用关键字abstract修饰方法称为修饰方法称为abstract方法,也称为方法,也称为抽象方法。抽象方法只能包含在抽象类中,是一种仅抽象方法。抽象方法只能包含在抽象类中,是一种仅有方法声明而没有方法体的方法。有方法声明而没有方法体的方法。抽象方法只能包含在抽象类中,当一个方法为抽象方抽象方法只能包含在抽象类中,当一个方法为抽象方法时,意味着这个方法必须被子类的方法所重写,否法时,意味着这个方法必须被子类的方法所重写,否则其子类的该方法仍然是则其子类的该方法仍然是abstract的,而这个子类也的,而这个子类也必须是抽象的,即声明为必须是抽象的,即声明为abstract。abstract不能与不能与private、static、final并列修饰同一并列修饰同一个方法,即构造方法、静态方法、个方法,即构造方法、静态方法、private方法不能被方法不能被定义为抽象方法。定义为抽象方法。几个特殊方法几个特殊方法构造方法构造方法在在Java语言成员方法中,有一种特殊的方法,其与类语言成员方法中,有一种特殊的方法,其与类同名,类创建对象时,总是使用它来初始化对象,这同名,类创建对象时,总是使用它来初始化对象,这个方法称为构造方法。个方法称为构造方法。构造方法的定义格式为:构造方法的定义格式为:构造方法名构造方法名(形式参数表形式参数表)方法体方法体从上面的定义格式可以看出,构造方法与成员从上面的定义格式可以看出,构造方法与成员方法有明显的区别:方法有明显的区别:不能被不能被static、final、synchronized和和abstract修饰;修饰;不含返回值的类型,方法体中也不能使用不含返回值的类型,方法体中也不能使用return语句返回一个值,而且构造方法不能定语句返回一个值,而且构造方法不能定义成义成void,在定义构造方法时加了,在定义构造方法时加了“void”,这个方法就变成了成员方法。这个方法就变成了成员方法。构造方法名必须与类同名。构造方法名必须与类同名。maiain()方法方法在在Java中,中,main()方法是方法是Java应用程序的入口方法,应用程序的入口方法,也就是说,也就是说,Java应用程序在运行的时候,第一个执行应用程序在运行的时候,第一个执行的方法就是的方法就是main()方法,这个方法和其他的方法有很方法,这个方法和其他的方法有很大的不同,方法的名字必须是大的不同,方法的名字必须是main,方法的访问控制,方法的访问控制符必须是符必须是public非访问控制符必须是非访问控制符必须是static,即类方法,即类方法,无返回值,即返回值的类型为无返回值,即返回值的类型为void,方法的参数必须,方法的参数必须是一个字符串数组。是一个字符串数组。方法重载方法重载在类中可以创建多个方法,它们具有相同的名字,但在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数,或者参数的类型不同,或者参数的具有不同的参数,或者参数的类型不同,或者参数的个数不同,这就是方法的重载。个数不同,这就是方法的重载。Java程序运行时,通程序运行时,通过传递给方法的不同个数和类型的参数来决定具体使过传递给方法的不同个数和类型的参数来决定具体使用哪个方法,这就是用哪个方法,这就是Java语言的多态性。语言的多态性。例如:例如:classPeopleStringid,name;People()/构造方法构造方法id=0000;name=null;People(Stringid,Stringname)/同名构造方法,参数不同同名构造方法,参数不同this.id=id;this.name=name;voidsetName(Stringname)this.name=name;StringgetName()returnname;publicstaticvoidmain(Stringargs) People p=new People(); / People p=new People(); /采用无参构造方法创建对象采用无参构造方法创建对象p People q=new People(0001, People q=new People(0001,清华大学清华大学);/采用带参构造方法创建对象采用带参构造方法创建对象qp.setName(John);q.setName(Mike); System.out.println( System.out.println(对象对象p的编号:的编号:+p.id+,+姓名:姓名:+p.getName(); System.out.println( System.out.println(对象对象q的编号:的编号:+q.id+,+姓名:姓名:+q.getName();3.1.4对象对象对象的创建对象的创建声明对象声明对象声明对象的一般格式为:声明对象的一般格式为:类类 对象名对象名;例如:例如:PeopleMike;实例化对象实例化对象使用使用new关键词和构造方法为对象分配存储空间,即关键词和构造方法为对象分配存储空间,即实例化对象。实例化对象的其格式如下:实例化对象。实例化对象的其格式如下:new类名类名(参数列表参数列表);对象的使用对象的使用对象名是用来引用对象的,对象的变量和方法可以通对象名是用来引用对象的,对象的变量和方法可以通过对象名来引用,所以对象名也称为对该对象的引用过对象名来引用,所以对象名也称为对该对象的引用(Reference)。)。Java中使用变量和方法的格式为:中使用变量和方法的格式为:对象名对象名.成员变量名成员变量名;对象名对象名.方法名方法名(形式参数表形式参数表);对象的释放对象的释放Java语言自动管理内存,可以自动进行垃圾收集,在语言自动管理内存,可以自动进行垃圾收集,在收集前自动调用对象的收集前自动调用对象的finalize()方法来释放系统资源。方法来释放系统资源。Java程序设计基础与实践 第4章继承与多态Java类间继承的实现方法类间继承的实现方法Java继承中变量与方法的隐藏和覆盖问题继承中变量与方法的隐藏和覆盖问题this和和super关键字的使用关键字的使用Java多态性的含义多态性的含义4.1.1继承性继承性创建子类创建子类Java中,使用关键字中,使用关键字extends实现继承,格式如下:实现继承,格式如下:类修饰符类修饰符class类名类名extends父类名父类名 implements接口列表接口列表/类声明类声明继承而得到的类称为子类,被继承的类称为父类、基继承而得到的类称为子类,被继承的类称为父类、基类或超类。类或超类。Java不支持多重继承,即一个类从多个父不支持多重继承,即一个类从多个父类派生的能力。子类可以继承父类中所有可被子类访类派生的能力。子类可以继承父类中所有可被子类访问的成员变量和成员方法。问的成员变量和成员方法。所有的类都是通过直接或间接地继承所有的类都是通过直接或间接地继承java.lang.Object类得到的。类得到的。例如:例如: classPeopleStringid,name;intage;People()id=00000;name=null;age=0;voidsetName(Stringname)this.name=name;StringgetName()returnname;public class Student extends People /public class Student extends People /定义定义Student类,继承类,继承People类类 String number; /String number; /定义自己的成员变量:学号定义自己的成员变量:学号publicstaticvoidmain(Stringargs) Student s=new Student(); / Student s=new Student(); /创建对象创建对象 s.age=20; /s.age=20; /继承父类成员变量继承父类成员变量 s.number=15; /s.number=15; /自己的成员变量自己的成员变量 s.setName(s.setName(黎明黎明);/继承父类的成员方法继承父类的成员方法 System.out.println(System.out.println(学号:学号:+s.number);/输出信息输出信息 System.out.println(System.out.println(姓名:姓名:+s.getName(); System.out.println( System.out.println(年龄:年龄:+s.age);对象的上转型对象对象的上转型对象上转型(上转型(Upercase)对象,即将子类实例化的对象的)对象,即将子类实例化的对象的引用赋给用父类声明的变量。即定义了子类对象,但引用赋给用父类声明的变量。即定义了子类对象,但把这个对象的引用放到父类的对象中。把这个对象的引用放到父类的对象中。例如,假设例如,假设A类是类是B类的父类类的父类Aa;A=newB();或或Aa;Bb=newB();a=b;称这个父类对象称这个父类对象a是子类对象是子类对象b的上转型对象。的上转型对象。例如:例如:classPeopleprotected String name=protected String name=张三张三;protectedintage,number;StringgetName()returnname;protectedStringgetInfo(Strings,inta,intn)name=s;age=a;number=n;return return 父类姓名:父类姓名:+name+n+父类年龄:父类年龄:+age+n+父类工号:父类工号:+number+n;classStudentextendsPeopleprotected String name=protected String name=李四李四;/变量的隐藏变量的隐藏protectedStringgetInfo(Strings,inta)name=s;age=a;return return 子类姓名:子类姓名:+name+n+子类年龄:子类年龄:+age+n;protected String getInfo(String s,int a,int n) /protected String getInfo(String s,int a,int n) /方法的重写方法的重写name=s;age=a;number=n;return return 子类姓名:子类姓名:+name+n+子类年龄:子类年龄:+age+n+子类工号:子类工号:+number+n;publicstaticvoidmain(Stringargs)People p=new Student(); /pPeople p=new Student(); /p为上转型对象为上转型对象/System.out.println(p.getInfo(p.getName(),20); / /非法,上转型对象不可以访问子类新增成员非法,上转型对象不可以访问子类新增成员System.out.println(p.getInfo(p.getName(),40,10000);/访问子类重写的方法访问子类重写的方法,隐藏的变量隐藏的变量Students=(Student)p; / /强制转换为子类对象,可以访问自了新增的成员方法强制转换为子类对象,可以访问自了新增的成员方法System.out.println(s.getInfo(s.getName(),20); 隐藏和覆盖隐藏和覆盖隐藏就是子类隐藏了父类的变量或方法,那么,子类隐藏就是子类隐藏了父类的变量或方法,那么,子类不能访问父类被隐藏的变量或方法不能访问父类被隐藏的变量或方法。 Java中变量在继承时的覆盖和隐藏规则为:中变量在继承时的覆盖和隐藏规则为:父类的实例变量和静态变量能被子类的同名变量隐藏。父类的实例变量和静态变量能被子类的同名变量隐藏。局部变量和各种参数永远不会被隐藏。局部变量和各种参数永远不会被隐藏。classParentClassprivate static String privateField = private static String privateField = 父类变量父类变量-private;/* friendly */String friendlyField = /* friendly */String friendlyField = 父类变量父类变量-friendly;protected static String protectedField = protected static String protectedField = 父类变量父类变量-protectedstatic;protected String publicField = protected String publicField = 父类变量父类变量-public;publicStringgetPrivateFieldValue()returnprivateField;publicclassSubClassextendsParentClassprivate String privateField = private String privateField = 子类变量子类变量-private;/* friendly */String friendlyField = /* friendly */String friendlyField = 子类变量子类变量-friendly;protected static String protectedField = protected static String protectedField = 子类变量子类变量-protectedstatic;public String publicField = public String publicField = 子类变量子类变量-public;publicStringgetPrivateFieldValue()/System.out.println(super.publicField);returnprivateField;publicstaticvoidmain(Stringargs) / / 输出下列三种情况中变量的值输出下列三种情况中变量的值 / ParentClass/ ParentClass类型,类型,ParentClass对象对象 ParentClassparentClass=newParentClass();System.out.println(ParentClassparentClass=newParentClass(););System.out.println(parentClass.getPrivateFieldValue();System.out.println(parentClass.friendlyField);System.out.println(parentClass.protectedField);System.out.println(parentClass.publicField);System.out.println(); / ParentClass / ParentClass类型,类型,SubClass对象对象 ,上转型对象,上转型对象ParentClasssubClass=newSubClass();System.out.println(ParentClasssubClass=newSubClass(););System.out.println(subClass.getPrivateFieldValue();System.out.println(subClass.friendlyField);System.out.println(subClass.protectedField);System.out.println(subClass.publicField);System.out.println(); / SubClass / SubClass类型,类型,SubClass对象对象 SubClasssubClazz=newSubClass();System.out.println(SubClasssubClazz=newSubClass(););System.out.println(subClazz.getPrivateFieldValue();System.out.println(subClazz.friendlyField);System.out.println(subClazz.protectedField);System.out.println(subClazz.publicField);方法的隐藏和覆盖方法的隐藏和覆盖classParentpublicstaticStringkind=javastudy.extendsstudy.parent;publicstaticintage=50;publicStringname=Parent; / /静态方法,返回包名静态方法,返回包名 publicstaticStringgetKind() System.out.println(parent System.out.println(parent的的getKind()方法被调用了方法被调用了);returnkind; / /静态方法,返回年龄静态方法,返回年龄 publicstaticintgetAge() System.out.println(Parent System.out.println(Parent的的getAge()方法被调用了方法被调用了);returnage; / /实例方法,返回姓名实例方法,返回姓名 publicStringgetName() System.out.println(Parent System.out.println(Parent的的getName()方法被调用了方法被调用了);returnthis.name;/子类子类 classChildextendsParentpublicstaticStringkind=javastudy.extendsstudy.child;publicintage=25;publicStringname=child; / /隐藏父类静态方法隐藏父类静态方法publicstaticStringgetKind() System.out.println(child System.out.println(child的的getkind()方法被调用了方法被调用了);returnkind; / /获取父类包名获取父类包名 publicstaticStringgetParentKind()returnParent.kind; / /覆盖父类实例方法覆盖父类实例方法 publicStringgetName() System.out.println(child System.out.println(child的的getName()被调用了被调用了);returnthis.name; / /获取父类名称获取父类名称 publicStringgetParentName()returnsuper.name;/* * *错误,实例方法不能覆盖父类的静态方法错误,实例方法不能覆盖父类的静态方法 publicintgetAge()returnage;*/publicclassmethodExtendmethodExtendpublicstaticvoidmain(Stringargs)Childchild=newChild(); System.out.println( System.out.println(子类名称:子类名称:%s,年龄:年龄:%d,包名包名:%s%n+child.name+child.age+child.kind); / /输出:子类名称:输出:子类名称:child,年龄:年龄:25,包包:javastudy.extendsstudy.child / /把把child转换成转换成parent对象对象Parentparent=child; System.out.println( System.out.println(转换后的名称转换后的名称:%s,年龄年龄:%d,包名包名:%s%n+parent.name+parent.age+parent.kind); / /输出:转换后的名称输出:转换后的名称:Parent,年龄:年龄:50,包:包:javastudy.extendsstudy.parent System.out.println( System.out.println(子类访问父类被隐藏的实例变量子类访问父类被隐藏的实例变量name:%s%n+child.getParentName(); / /输出:子类访问父类被隐藏的实例变量输出:子类访问父类被隐藏的实例变量name:Parent System.out.println( System.out.println(子类访问父类被隐藏的静态变量子类访问父类被隐藏的静态变量kind:%s+child.getParentKind(); / /输出:子类访问父类被隐藏的静态变量输出:子类访问父类被隐藏的静态变量kind:javastudy.extendsstudy.parentchild.getName(); / /输出:输出:child的的getName()被调用了被调用了 /*/*注意看这个方法,返回的还是子类的注意看这个方法,返回的还是子类的getNameparent.getName(); / /输出:输出:child的的getName()被调用了被调用了 child.getKind(); / /输出:输出:child的的getkind()方法被调用了方法被调用了 parent.getKind(); / /输出:输出:parent的的getKind()方法被调用了方法被调用了 this和和superthis this指明当前对象,当一个方法引用它自己类的实例变指明当前对象,当一个方法引用它自己类的实例变量和方法时,每个引用前都隐含着量和方法时,每个引用前都隐含着“this”。 另外,另外,this还可以用在重载的构造方法中,用来引用其还可以用在重载的构造方法中,用来引用其它的构造方法,一般格式是它的构造方法,一般格式是this(参数列表参数列表)。例如:例如:classPeopleprotectedStringname,id;protectedintage; People(String name)/ People(String name)/第一个构造方法第一个构造方法 this.name=name; /thisthis.name=name; /this不能省略,引用成员变量不能省略,引用成员变量 People(String name,int age)/ People(String name,int age)/第二个构造方法第二个构造方法 this(name); /this(name); /调用第一个构造方法调用第一个构造方法this.age=age; / /通过构造方法初始化人类的基本信息通过构造方法初始化人类的基本信息 People(String name,int age,String id)/People(String name,int age,String id)/第三个构造方法第三个构造方法 this(name,age); /this(name,age); /调用第二个构造方法调用第二个构造方法this.id=id; / /通过方法通过方法getInfo()获取人类基本信息获取人类基本信息protectedStringgetInfo(Stringname,intage,Stringid)this.name=name;this.age=age;this.id=id; return return 姓名:姓名:+this.name+n+年龄:年龄:+this.age+n+工号:工号:+this.id+n;publicstaticvoidmain(Stringagrs) People p=new People(Mike,30,0001);/ People p=new People(Mike,30,0001);/调用第三个构造方法调用第三个构造方法 String str=String str=姓名:姓名:+p.name+n+年龄:年龄:+p.age+n+工号:工号:+p.id+n;System.out.println(str); System.out.println(p.getInfo(Mike,30,0001);/ System.out.println(p.getInfo(Mike,30,0001);/通过方法通过方法getInfo()获取人类基本信息获取人类基本信息supersuper关键字的作用是用于子类引用父类的成员,如变关键字的作用是用于子类引用父类的成员,如变量、方法或者构造方法。量、方法或者构造方法。使用的格式是使用的格式是“super.成员名成员名”此外,使用此外,使用super(参数列表参数列表)就可以调用父类的构造就可以调用父类的构造方法了,如果父类中有多个构造方法,系统将自动根方法了,如果父类中有多个构造方法,系统将自动根据据super中的参数个数和参数类型来匹配父类中的构造中的参数个数和参数类型来匹配父类中的构造方法。方法。例如:例如: classPeopleprotectedStringname,id;protectedintage;People(Stringname,intage,Stringid)this.name=name;this.age=age;this.id=id;protectedStringgetInfo(Stringname,intage,Stringid)this.name=name;this.age=age;this.id=id; return return 父类姓名:父类姓名:+name+n+父类年龄:父类年龄:+age+n+父类工号:父类工号:+id+n;classStudentextendsPeopleStudent(Stringname,intage,Stringid) super(name,age,id); / super(name,age,id); /调用父类的构造方法调用父类的构造方法 public String getInfo(String name,int age,String id) / public String getInfo(String name,int age,String id) /方法方法的重写的重写this.name=name;this.age=age;this.id=id; return return 子类姓名:子类姓名:+name+n+子类年龄:子类年龄:+age+n+子子类工号:类工号:+id+n;StringgetSuperInfo() / /调用父类方法调用父类方法getInfo()returnsuper.getInfo(name,age,id);publicstaticvoidmain(Stringargs)Peoplep=newPeople(Mike,30,0001);Students=newStudent(John,20,15);System.out.println(p.getInfo(p.name,p.age,p.id);System.out.println(s.getInfo(s.name,s.age,s.id);System.out.println(s.getSuperInfo();构造方法的继承构造方法的继承父类中的构造方法也可以被子类继承,使用时应当遵父类中的构造方法也可以被子类继承,使用时应当遵循以下原则:循以下原则:子类可以在自己的构造方法中使用子类可以在自己的构造方法中使用super(形式参数表形式参数表)来调用父类的构造方法。使用来调用父类的构造方法。使用this(形式参数表形式参数表)来调用来调用本类的构造方法。本类的构造方法。如果调用父类的构造方法,则必须写在子类构造方法如果调用父类的构造方法,则必须写在子类构造方法的第一行。的第一行。如果子类的构造方法中没有显式的调用父类的构造方如果子类的构造方法中没有显式的调用父类的构造方法,则系统默认调用父类的无参数构造方法。法,则系统默认调用父类的无参数构造方法。如果子类构造方法中既没有显式的调用父类的构造方法,如果子类构造方法中既没有显式的调用父类的构造方法,而父类中又没有无参的构造方法,则编译出错。而父类中又没有无参的构造方法,则编译出错。例如:例如: classAnimalAnimal()System.out.println(System.out.println(动物不会说话动物不会说话!);classPersonextendsAnimalStringstr;Person(Stringstr)/隐含调用父类的无参构造方法隐含调用父类的无参构造方法Animal()this.str=str;System.out.println(System.out.println(人类使用人类使用+str+交流。交流。);Person()/隐含调用父类的无参构造方法隐含调用父类的无参构造方法Animal()this(this(语言语言);classChineseextendsPersonStrings;Chinese(Strings)super(super(肢体动作肢体动作);/显式调用父类的构造方法显式调用父类的构造方法Person(Stringstr)this.s=s;System.out.println(System.out.println(中国人的语言是中国人的语言是+s+。);Chinese()/隐含调用父类的无参构造方法隐含调用父类的无参构造方法Person()System.out.println(System.out.println(中国人最棒!中国人最棒!);publicstaticvoidmain(Stringargs)Chinese t1=new Chinese(Chinese t1=new Chinese(汉语汉语);/调用的构造方法为调用的构造方法为Chinese(Strings)Chineset2=newChinese();/调用的构造方法为调用的构造方法为Chinese()4.1.2多态性多态性J Java中多态性的实现是指程序运行时动态绑定调用的中多态性的实现是指程序运行时动态绑定调用的方法,换句话说,具有多态性的方法名称是相同的,方法,换句话说,具有多态性的方法名称是相同的,但是它们会以不同数量、不同类型的参数来进行区分,但是它们会以不同数量、不同类型的参数来进行区分,运行时根据调用方法的参数和类型来动态决定绑定哪运行时根据调用方法的参数和类型来动态决定绑定哪个方法。个方法。例如:例如:publicclassPeople/定义一个基类定义一个基类Stringname;intage;publicStringgetName()returnPeople:+name;publicvoidsetName(Stringname)this.name=name;/ /定义两个派生类定义两个派生类classTeacherextendsPeopleStringid;publicTeacher(Stringid,intage)this.id=id;this.age=age; publicStringgetName()returnTeacher:+name;classStudentextendsPeopleStringnumber;publicStudent(Stringnumber,intage)this.number=number;this.age=age; publicStringgetName()returnStudent:+name;/ /测试输出结果的类测试输出结果的类classShowInfopublicstaticvoidmain(Stringargs)Peoplep;Teachert=newTeacher(0001,40);Students=newStudent(15,20); p=t; / p=t; /上转型对象上转型对象 p.setName(Mike);System.out.print(t.id+,);System.out.print(p.getName()+,);System.out.println(p.age);p=s;p.setName(John);System.out.print(s.number+,);System.out.print(p.getName()+,);System.out.println(p.age);Java程序设计基础与实践 第5章接口和包Java接口的定义与继承接口的定义与继承Java接口的实现接口的实现Java接口与类的关系,特别是接口与抽象类的接口与类的关系,特别是接口与抽象类的区别区别Java包的声明、创建和使用方法包的声明、创建和使用方法JAR命令的用法命令的用法5.1.1接口接口Java不支持多继承性,也就是一个类只能有一个父亲。不支持多继承性,也就是一个类只能有一个父亲。单继承性使单继承性使Java易于管理,但为了克服单继承的缺点,易于管理,但为了克服单继承的缺点,Java使用了接口,一个类可以实现多个接口。使用了接口,一个类可以实现多个接口。接口的定义接口的定义接口的定义包括接口声明和接口体。接口的定义包括接口声明和接口体。Java使用关键字使用关键字interface声明接口,格式如下:声明接口,格式如下:修饰符修饰符interface接口名接口名 extends父接口列表父接口列表/接接口声明口声明接口体接口体接口的实现接口的实现一个类通过使用关键字一个类通过使用关键字implements实现一个或多个接实现一个或多个接口。如果使用多个接口,用逗号隔开接口名,格式如口。如果使用多个接口,用逗号隔开接口名,格式如下:下:类修饰符类修饰符class类名类名extends父类名父类名implements接口列表接口列表/类声明类声明例如:例如: interface Information /interface Information /定义接口定义接口String college=String college=清华大学清华大学;/接口常量接口常量void setName(String name); /void setName(String name); /接口方法接口方法StringgetName();interfaceCourseString professional=String professional=计算机应用计算机应用;voidsetCourse(Stringcourse);StringgetCourse();/实现接口实现接口publicclassTeacherimplementsInformation,CourseStringname,course;/重写接口方法,注意不要丢掉重写接口方法,注意不要丢掉publicpublicvoidsetName(Stringname)this.name=name;publicStringgetName()return return 教师姓名:教师姓名:+name;publicvoidsetCourse(Stringcourse)this.course=course;publicStringgetCourse()return return 主讲课程:主讲课程:+course;publicstaticvoidmain(Stringargs)Teachert=newTeacher();t.setName(t.setName(张强张强);t.setCourse(Javat.setCourse(Java程序设计程序设计);System.out.println(t.getName();/使用接口常量使用接口常量System.out.println(System.out.println(所在院校:所在院校:+t.college);System.out.println(System.out.println(技术专业:技术专业:+t.professional);System.out.println(t.getCourse();接口的继承接口的继承 接口支持多继承,子接口可以继承父接口接口支持多继承,子接口可以继承父接口成员,当一个非抽象类实现一个子接口成员,当一个非抽象类实现一个子接口时,它必须实现所有接口(包含父接口)时,它必须实现所有接口(包含父接口)的所有方法。的所有方法。例如:例如: interface Information /interface Information /定义接口定义接口String college=String college=清华大学清华大学;/接口常量接口常量void setName(String name); /void setName(String name); /接口方法接口方法StringgetName();interface Course extends Information /interface Course extends Information /接口的继承接口的继承String professional=String professional=计算机应用计算机应用;voidsetCourse(Stringcourse);StringgetCourse();/实现接口实现接口publicclassTeacherimplementsCourseStringname,course;/实现父接口的方法实现父接口的方法publicvoidsetName(Stringname)this.name=name;publicStringgetName()return return 教师姓名:教师姓名:+name;publicvoidsetCourse(Stringcourse)this.course=course;publicStringgetCourse()return return 主讲课程:主讲课程:+course;publicstaticvoidmain(Stringargs)Teachert=newTeacher();t.setName(t.setName(张强张强);t.setCourse(Javat.setCourse(Java程序设计程序设计);System.out.println(t.getName();/使用接口常量使用接口常量System.out.println(System.out.println(所在院校:所在院校:+t.college);System.out.println(System.out.println(技术专业:技术专业:+t.professional);System.out.println(t.getCourse();接口回调接口回调 接口回调是指可以把实现某一接口的类创接口回调是指可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口建的对象的引用赋给该接口声明的接口变量中,那么该接口变量就可以调用被变量中,那么该接口变量就可以调用被类实现的接口中的方法。类实现的接口中的方法。例如:例如:interface Information /interface Information /定义接口定义接口String college=String college=清华大学清华大学;/接口常量接口常量void setName(String name); /void setName(String name); /接口方法接口方法StringgetName();interfaceCourseString professional=String professional=计算机应用计算机应用;voidsetCourse(Stringcourse);StringgetCourse();/实现接口实现接口publicclassTeacherimplementsInformation,CourseStringname,course;/实现接口的方法实现接口的方法publicvoidsetName(Stringname)this.name=name;publicStringgetName()return return 教师姓名:教师姓名:+name;publicvoidsetCourse(Stringcourse)this.course=course;publicStringgetCourse()return return 主讲课程:主讲课程:+course;publicstaticvoidmain(Stringargs)Teachert=newTeacher();Information info=t; /Information info=t; /接口回调接口回调Coursec=t;/调用调用Teacher类实现的方法类实现的方法info.setName(info.setName(张强张强);c.setCourse(Javac.setCourse(Java程序设计程序设计);System.out.println(info.getName();/使用接口常量使用接口常量System.out.println(System.out.println(所在院校:所在院校:+t.college);System.out.println(System.out.println(技术专业:技术专业:+t.professional);System.out.println(c.getCourse();接口和抽象类接口和抽象类接接口口抽象类抽象类静态常量静态常量一般变量、常量、静态变量、静态常量一般变量、常量、静态变量、静态常量抽象方法抽象方法成员方法、静态方法、抽象方法、抽象静态方法成员方法、静态方法、抽象方法、抽象静态方法使用关键字使用关键字interface使用关键字使用关键字abstract表表5 5.1接口和抽象类的区别接口和抽象类的区别5.1.2包包包的概念包的概念Java系统中存在大量的类和接口,为了更系统中存在大量的类和接口,为了更好地组织它们,好地组织它们,Java提供了包机制,包提供了包机制,包是类和接口的组织方式,包类似于操作是类和接口的组织方式,包类似于操作系统中的文件夹,将相近功能的类打入系统中的文件夹,将相近功能的类打入同一包,将不同功能的类打入不同的包同一包,将不同功能的类打入不同的包内,实现类的分类组织。内,实现类的分类组织。包的声明包的声明 使用关键字使用关键字package声明一个包,格式声明一个包,格式如下:如下:package包名包名;例如:例如: packagepeople;声明包语句必须添加在源程序的第一行,声明包语句必须添加在源程序的第一行,表示该程序文件声明的全部类都属于这表示该程序文件声明的全部类都属于这个包,包的名字一般都是由小写单词组个包,包的名字一般都是由小写单词组成。成。包的创建包的创建手动创建包手动创建包 首先编译源文件,然后在当前目录创建一首先编译源文件,然后在当前目录创建一个文件夹,文件夹的名称与包名一致,个文件夹,文件夹的名称与包名一致,然后将生成的字节码文件放入该文件夹然后将生成的字节码文件放入该文件夹中,此时运行中,此时运行Java程序命令修改改为:程序命令修改改为:java包名包名.类名。类名。例如:例如: package people; /package people; /声明包声明包interfaceInformationString college=String college=清华大学清华大学;voidsetName(Stringname);StringgetName();publicclassPeopleimplementsInformationprotectedStringname;protectedintage,number;public public People(intage,intnumber)this.age=age;this.number=number;publicvoidsetName(Stringname)this.name=name;publicStringgetName()return return 姓名:姓名:+name;publicstaticvoidmain(Stringargs)Peoplep=newPeople(40,10000);p.setName(p.setName(张强张强);System.out.println(System.out.println(工号:工号:+p.number);System.out.println(p.getName();System.out.println(System.out.println(年龄:年龄:+p.age);自动创建包自动创建包Java中使用中使用javacd命令将类文件生成到指定的路径,命令将类文件生成到指定的路径,格式如下:格式如下:javacd类文件生成的路径类文件生成的路径 源文件名源文件名如果将类文件生成在当前路径的包中,如果将类文件生成在当前路径的包中,“类文件生成类文件生成的路径的路径”可以使用可以使用“.”代替。代替。编译上面程序的命令:编译上面程序的命令:javac-d.People.java解释上面程序的命令:解释上面程序的命令:javapeople.People包的使用包的使用如果某个类不再当前类的目录下,则使用包名如果某个类不再当前类的目录下,则使用包名.类名类名的方式使用类,例如,如果的方式使用类,例如,如果People类不在当前类目录类不在当前类目录下,其目录为下,其目录为people,则使用,则使用People类的方法为:类的方法为:people.People=newpeople.People(40,10000);如果要在程序中直接引用类名,则必须使用如果要在程序中直接引用类名,则必须使用import语句,例如:语句,例如:importpeople.People;如果要导入包中所有的类,可以使用如果要导入包中所有的类,可以使用“*”“*”,例如:,例如:importpeople.*;import语句应该在程序的语句应该在程序的package语句后,例如:语句后,例如:packageteacher;importpeople.People;/导入导入people包中的类包中的类PeopleJava提供的常用包提供的常用包java.lang包包java.io包包java.util包包java.awt包包java.swing包包java.applet包包java.net包包java.sql包包JAR文件包文件包JAR命令的用法如下:命令的用法如下:jarctxuvfm0Mjar-文件文件manifest-文件文件-C目目录录文件名列表文件名列表Java程序设计基础与实践 第6章异常处理Java异常体系结构异常体系结构Java异常处理机制异常处理机制Java异常的捕获、处理方法异常的捕获、处理方法Java自定义异常的定义、抛出方法自定义异常的定义、抛出方法6.1.1Java异常体系结构及处理机制异常体系结构及处理机制异常的概念异常的概念异常(异常(Exception)又称为例外,是指在程序运行过程)又称为例外,是指在程序运行过程中发生的非正常事件,如用户数据输入错误、程序代中发生的非正常事件,如用户数据输入错误、程序代码错误、文件找不到、对空对象进行操作等错误。异码错误、文件找不到、对空对象进行操作等错误。异常事件的发生,中断了程序的正常执行,可能带来严常事件的发生,中断了程序的正常执行,可能带来严重的后果和损失。重的后果和损失。Java异常体系结构异常体系结构Java系统中提供了许多异常类,这些类又称为标准异系统中提供了许多异常类,这些类又称为标准异常类,分布在常类,分布在Java.lang、Java.io、Java.util和和Java.net包中。所有的异常都是由一个称为包中。所有的异常都是由一个称为Throwable类及其子类派生出来的,其层次结构如类及其子类派生出来的,其层次结构如图图6.1所示。所示。图图6.1JavaJava异常体系结构异常体系结构ThrowableThrowable类是类是Java语言中所有错误或异常的超类。语言中所有错误或异常的超类。Error与与ExceptionError是是Throwable的子类,是程序无法处理的错误。的子类,是程序无法处理的错误。Exception类及其子类是类及其子类是Throwable的子类,是程序本的子类,是程序本身可以处理的异常,这种异常分运行时异常身可以处理的异常,这种异常分运行时异常(RuntimeException)和非运行时异常两大类。)和非运行时异常两大类。运行时异常和非运行时异常运行时异常和非运行时异常运行时异常是在运行时异常是在Java虚拟机正常运行期间抛出的异常虚拟机正常运行期间抛出的异常的超类,的超类,Java编译器不去检查它,也就是说,当程序编译器不去检查它,也就是说,当程序中可能出现这类异常时,会编译通过,因此也称之为中可能出现这类异常时,会编译通过,因此也称之为不检查异常(不检查异常(UncheckedException)。)。运行时异常运行时异常说明说明ArithmeticException除数为除数为0引起的异常。引起的异常。IndexOutOfBoundsException由于数组下标越界或字符访问越界引起异常。由于数组下标越界或字符访问越界引起异常。ArrayStoreException数组存储空间不够引起的异常。数组存储空间不够引起的异常。IllegalArgumentException使用非法参数引起的异常。使用非法参数引起的异常。IllegalThreadStateException线程调用某个方法而所处状态不适当,引起异常。线程调用某个方法而所处状态不适当,引起异常。NumberFormatException字符的字符的UTF代码数据格式错误引起的异常。代码数据格式错误引起的异常。NegativeArraySizeException数组长度为负数产生的异常。数组长度为负数产生的异常。NullPionterException访问一个空数组中的元素或访问空对象中的成员引起的异常。访问一个空数组中的元素或访问空对象中的成员引起的异常。表表6.1常见的常见的运行时异常运行时异常非运行时异常是非运行时异常是RuntimeException以外的异常,也称以外的异常,也称为检查异常(为检查异常(CheckedException),类型上都属于),类型上都属于CheckedException类及其子类。从程序语法角度讲类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编是必须进行处理的异常,如果不处理,程序就不能编译通过,所以一般情况下编写程序时不自定义检查异译通过,所以一般情况下编写程序时不自定义检查异常,常见非运行时异常如表常,常见非运行时异常如表6.2所示。所示。非运行时异常非运行时异常说明说明ClassNotFoundException指定名字的类或接口未找到。指定名字的类或接口未找到。IllegalAccessException试图访问在另一个包的类中的方法,而该方法未声明为试图访问在另一个包的类中的方法,而该方法未声明为public。InstantiationException试图创建抽象类或接口的对象。试图创建抽象类或接口的对象。InterruptedException其他线程中断了当前线程时发生的异常。其他线程中断了当前线程时发生的异常。IOException请求的请求的I/O操作无法完成。操作无法完成。EOFException在输入操作结束前遇到了文件尾。在输入操作结束前遇到了文件尾。FileNotFoundException未找到指定的文件或目录所引起的异常。未找到指定的文件或目录所引起的异常。InterruptedIOExceptionI/O:操作被中断。:操作被中断。UTFDataFormatExceptionUnicode文本格式的数据格式错误。文本格式的数据格式错误。SQLException数据库访问错误。数据库访问错误。ProtocolException网络协议的执行错误。网络协议的执行错误。SocketException有关有关Socket的操作无法正常完成。的操作无法正常完成。UnknowHostException网络客户方指出的服务器地址有误。网络客户方指出的服务器地址有误。UnknownServiceException网络连接不能支持请求服务。网络连接不能支持请求服务。表表6.2常见的常见的非运行时异常非运行时异常Java异常分类异常分类Java异常类有两个来源,一是异常类有两个来源,一是Java语言本身定义的一语言本身定义的一些基本异常类型,二是用户通过继承些基本异常类型,二是用户通过继承Exception类或者类或者其子类自己定义的异常。其子类自己定义的异常。Java异常的处理方法异常的处理方法Java采用面向对象的方法来处理异常。在一个方法的采用面向对象的方法来处理异常。在一个方法的运行过程中,如果发生了异常,则这个方法生成代表运行过程中,如果发生了异常,则这个方法生成代表该异常的一个对象,并把它交给运行时系统,运行时该异常的一个对象,并把它交给运行时系统,运行时系统寻找相应的代码来处理这一异常。系统寻找相应的代码来处理这一异常。6.1.2异常的捕获和处理异常的捕获和处理异常处理的基本结构异常处理的基本结构在在Java中,异常处理的基本结构是:中,异常处理的基本结构是:try/可能出现特定异常的代码可能出现特定异常的代码catch(异常类型异常类型 异常的变量名异常的变量名)/异常处理代码异常处理代码finally/异常发生,方法返回之前,最终执行的代码异常发生,方法返回之前,最终执行的代码try、catch、finally三个语句块应注意的问题三个语句块应注意的问题try、catch、finally三个语句块均不能单独使用,三个语句块均不能单独使用,三者可以组成三者可以组成try.catch.finally、try.catch、try.finally三种结构,三种结构,catch语句可以有一个或多个,语句可以有一个或多个,finally语句最多只有一个。语句最多只有一个。try、catch、finally三个代码块中变量的作用域为三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些代码块个块中都可以访问,则需要将变量定义到这些代码块的外面。的外面。在有多个在有多个catch块的情况下,如果处理的异常类型块的情况下,如果处理的异常类型之间具有继承关系,应该首先捕获子类异常,再捕获之间具有继承关系,应该首先捕获子类异常,再捕获父类异常父类异常例如:例如:classTeacherStringname,number;intage,num;Teacher(Stringname,intage)this.name=name;this.age=age;voidsetNumber(Stringnumber)try /try /异常处理异常处理num=Integer.parseInt(number);catch(NumberFormatExceptione)System.out.println(System.out.println(工号格式错误!工号格式错误!);intgetNumber()returnnum;publicstaticvoidmain(Stringargs)Teacher t1=new Teacher(Teacher t1=new Teacher(黎明黎明,28);Teacher t2=new Teacher(Teacher t2=new Teacher(张力张力,30);t1.setNumber(2a001);t2.setNumber(22001);System.out.println(System.out.println(工号:工号:+t2.getNumber();6.1.3自定义异常自定义异常自定义异常类可以继承自定义异常类可以继承Throwable类或者类或者Exception,而不要继承而不要继承Error类,自定义异常类之间也可以有继承类,自定义异常类之间也可以有继承关系。关系。自定义异常必须使用自定义异常必须使用throws声明方法可能抛出的自定声明方法可能抛出的自定义异常,并用义异常,并用throw语句在适当的时候抛出自定义异常。语句在适当的时候抛出自定义异常。例如:例如: class MyException extends Exception /class MyException extends Exception /定义自定义异常定义自定义异常MyException() /MyException() /定义构造方法定义构造方法super();MyException(Strings)super(s);classTeacherStringname,number;intage;Teacher(Stringname,intage)this.name=name;this.age=age;voidsetNumber(Stringnumber)throwsMyExceptionif(number.equals(2a001)throw new MyException(throw new MyException(自定义异常自定义异常);elsethis.number=number;StringgetNumber()returnnumber;publicstaticvoidmain(Stringargs)Teacher t1=new Teacher(Teacher t1=new Teacher(黎明黎明,28);Teacher t2=new Teacher(Teacher t2=new Teacher(张力张力,30);tryt2.setNumber(22001);t1.setNumber(2a001);catch(MyExceptione)System.out.println(System.out.println(出现自定义异常!出现自定义异常!);finallySystem.out.println(System.out.println(工号:工号:+t2.getNumber();6.1.4抛出异常抛出异常使用使用throw关键字抛出异常关键字抛出异常throw关键字是用于方法体内部,用来抛出一个关键字是用于方法体内部,用来抛出一个Throwable类型的异常。类型的异常。throw语句的格式为:语句的格式为:throw异常类对象名异常类对象名;使用使用throws关键字声明抛出异常关键字声明抛出异常当方法的调用者不能处理该异常的时候,应该将它向当方法的调用者不能处理该异常的时候,应该将它向上传递,由调用它的方法来处理异常。上传递,由调用它的方法来处理异常。throws语句的语句的格式为:格式为:方法修饰符方法修饰符返回值的类型返回值的类型 成员方法名成员方法名(形式参数表形式参数表)throws异常表异常表/方法声明方法声明/方法体方法体例如:例如: classTeacherStringname,number;intage,num;Teacher(Stringname,intage)this.name=name;this.age=age;voidsetNumber(Stringnumber)throwsNumberFormatException/声明要抛出的异常声明要抛出的异常if(number.equals(2a001)/抛出异常抛出异常thrownewNumberFormatException();elsethis.number=number;StringgetNumber()returnnumber;publicstaticvoidmain(Stringargs)Teacher t1=new Teacher(Teacher t1=new Teacher(黎明黎明,28);Teacher t2=new Teacher(Teacher t2=new Teacher(张力张力,30);t1.setNumber(2a001); / /满足异常条件,系统会抛出异常满足异常条件,系统会抛出异常t2.setNumber(22001);System.out.println(t2.getNumber();6.1.5Throwable类中的常用方法类中的常用方法方法方法说明说明getCause()返回抛出异常的原因。如果返回抛出异常的原因。如果cause不存在或未知,则返回不存在或未知,则返回 null。getMessage()返回异常的消息信息。返回异常的消息信息。printStackTrace()功能是完成一个打印操作,在当前的标准输出上打印输出当前异常对象的堆栈使用轨迹,功能是完成一个打印操作,在当前的标准输出上打印输出当前异常对象的堆栈使用轨迹,也即程序先后调用执行了哪些对象或类的哪些方法,使得运行过程中产生了这个异常对也即程序先后调用执行了哪些对象或类的哪些方法,使得运行过程中产生了这个异常对象。象。t toString()()返回此返回此异常异常的简短描述。的简短描述。T Throwable(String message,Throwable cause )构造一个带指定详细消息和构造一个带指定详细消息和原因原因的新的新throwable。Throwable(Throwablecause)构造一个带指定构造一个带指定原因原因包含类和详细消息的新包含类和详细消息的新throwable。initCause(Throwablecause)将将throwable的原因的原因初始化为指定值。初始化为指定值。Exception(Stringmessage,Throwablecause)构造带指定详细消息和原因的新异常。构造带指定详细消息和原因的新异常。Exception(Throwablecause)根据指定的原因包含类和详细消息构造新异常根据指定的原因包含类和详细消息构造新异常。表表6.3Throwable类中的常用方法类中的常用方法例如:例如: classTeacherStringname,number;intage,num;Teacher(Stringname,intage)this.name=name;this.age=age;voidsetNumber(Stringnumber)try /try /异常处理异常处理num=Integer.parseInt(number);catch(NumberFormatExceptione)System.out.println(System.out.println(使用使用getMessage():+e.getMessage(); System.out.println( System.out.println(使用使用toString():+e.toString(); System.out.print( System.out.print(使用使用printStackTrace:);e.printStackTrace();intgetNumber()returnnum;publicstaticvoidmain(Stringargs)Teacher t1=new Teacher(Teacher t1=new Teacher(黎明黎明,28);Teacher t2=new Teacher(Teacher t2=new Teacher(张力张力,30);t2.setNumber(22001);System.out.println(System.out.println(工号:工号:+t2.getNumber();t1.setNumber(2a001);Java程序设计基础与实践 第7章布局管理和容器本章要点AWT与与SwingJava常用容器常用容器Java常用布局常用布局AWT与SwingAWT抽象窗口工具包(抽象窗口工具包(AbstractWindowtoolkit,AWT)提供了一套与)提供了一套与本地图形界面进行交互的接口。本地图形界面进行交互的接口。AWT中中的图形函数与操作系统所提供的图形函的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,称之为数之间有着一一对应的关系,称之为peers。当利用。当利用AWT来构建图形用户界来构建图形用户界面时,实际上是在利用操作系统所提供面时,实际上是在利用操作系统所提供的图形库,但是不同操作系统的图形库的图形库,但是不同操作系统的图形库所提供的功能不一样,在一个平台上存所提供的功能不一样,在一个平台上存在的功能在另外一个平台上则可能不存在的功能在另外一个平台上则可能不存在,所以为了实现在,所以为了实现Java语言所宣称的语言所宣称的“一次编译,到处运行一次编译,到处运行”,AWT不得不通不得不通过牺牲功能来实现其平台无关性,也就过牺牲功能来实现其平台无关性,也就是说,是说,AWT所提供的图形功能是各种通所提供的图形功能是各种通用型操作系统所提供的图形功能的交集。用型操作系统所提供的图形功能的交集。由于由于AWT是依靠本地方法来实现其功能是依靠本地方法来实现其功能的,通常把的,通常把AWT组件称为重量级组件。组件称为重量级组件。AWT是是Java最早用于编写图形界面应用最早用于编写图形界面应用程序的开发包。程序的开发包。AWT与Swing(续)SwingSwing是在是在AWT的基础上构建的一套的基础上构建的一套新的图形界面系统,它提供了新的图形界面系统,它提供了AWT所能所能够提供的所有功能,并且用纯粹的够提供的所有功能,并且用纯粹的Java代码对代码对AWT的功能进行了大幅度的扩充。的功能进行了大幅度的扩充。由于在由于在Swing中没有使用本地方法来实中没有使用本地方法来实现图形功能,通常把现图形功能,通常把Swing组件称为轻组件称为轻量级组件。量级组件。两者比较两者比较AWT是基于本地方法的是基于本地方法的C/C+程序,程序,其运行速度比较快;其运行速度比较快;Swing是基于是基于AWT的的Java程序,其运行速度比较慢。对于程序,其运行速度比较慢。对于一个嵌入式应用来说,目标平台的硬件一个嵌入式应用来说,目标平台的硬件资源往往非常有限,而应用程序的运行资源往往非常有限,而应用程序的运行速度又是项目中至关重要的因素。在这速度又是项目中至关重要的因素。在这种矛盾的情况下,简单而高效的种矛盾的情况下,简单而高效的AWT当当然成了嵌入式然成了嵌入式Java的第一选择;而在普的第一选择;而在普通的基于通的基于PC或者是工作站的标准或者是工作站的标准Java应应用中,硬件资源对应用程序所造成的限用中,硬件资源对应用程序所造成的限制往往不是项目中的关键因素,所以在制往往不是项目中的关键因素,所以在标准版的标准版的Java中则提倡使用中则提倡使用Swing,也,也就是通过牺牲速度来实现应用程序的功就是通过牺牲速度来实现应用程序的功能。能。常用容器Container类是所有容器类的父类,可类是所有容器类的父类,可以将组件添加到容器中。以将组件添加到容器中。Container也是也是Component的子类,的子类,因此也可以作为因此也可以作为组件添加到其他容器上。组件添加到其他容器上。Object的主要子类如图的主要子类如图7.1所示。所示。 容器从功能上可分为顶层容器、中间容容器从功能上可分为顶层容器、中间容器和特殊容器三种。器和特殊容器三种。 图7.1Object主要子类图顶层容器开发人员在使用开发人员在使用Java进行图形编程时,进行图形编程时,其组件需要放置在能够提供图形绘制的其组件需要放置在能够提供图形绘制的容器中,这样的容器就是顶层容器,也容器中,这样的容器就是顶层容器,也可以认为是一个窗口。在可以认为是一个窗口。在Swing中,有中,有JFrame、JDialog和和JApplet三种常用的三种常用的顶层容器。顶层容器。 JFrameJFrameJFrame用来设计类似于用来设计类似于Windows系统中系统中的窗口形式的应用程序。的窗口形式的应用程序。JFrame的常用方法的常用方法 :JFrame()创建一个无标题的窗口,窗口的默认布创建一个无标题的窗口,窗口的默认布局为局为BorderLayout布局布局JFrame(Strings)创建一个标题为创建一个标题为s的窗口的窗口,窗口的默认布窗口的默认布局为局为BorderLayout布局布局setBounds(inta,intb,intwidth,intheight)移动组件并调整其大小。由移动组件并调整其大小。由a和和b指定左指定左上角的新位置,由上角的新位置,由width和和height指定新的指定新的大小大小setSize(intwidth,intheight)设置窗口的大小,窗口在屏幕出现的默设置窗口的大小,窗口在屏幕出现的默认位置是认位置是(0,0)setVisible(Booleanb)设置窗口是可见还是不可见,窗口默认设置窗口是可见还是不可见,窗口默认是不可见的是不可见的JFrame(续)setResizable(Booleanb)设置窗口是否可调整大小,窗口默认设置窗口是否可调整大小,窗口默认是可调整大小的是可调整大小的setExtendedState(intstate)设置窗口的扩展状态,其中参数设置窗口的扩展状态,其中参数state取取Frame类中的下列类常量:类中的下列类常量:MAXIMIZED_HORIZ、MAXIMIZED_VERT、MAXIMIZED_BOTHsetDefaultCloseOperation(intoperation)设置用户在此窗体上发起设置用户在此窗体上发起“close”时默认执行的操作时默认执行的操作dispose()窗口调用该窗口调用该方法可以撤销当前窗口,并释放当前窗方法可以撤销当前窗口,并释放当前窗口所使用的资源口所使用的资源add(Componentcomp)将指定组件追加到此容器的尾部将指定组件追加到此容器的尾部pack()调整此窗口的大小,以适合其子组件的调整此窗口的大小,以适合其子组件的首选大小和布局。如果该窗口和首选大小和布局。如果该窗口和/或其所或其所有者仍不可显示,则两者在计算首选大有者仍不可显示,则两者在计算首选大小之前变得可显示。小之前变得可显示。JFrame(续)其中方法其中方法publicvoidsetDefaultCloseOperation(intoperation)的功能是设置用户在此窗体的功能是设置用户在此窗体上发起上发起“close”时默认执行的操作。必时默认执行的操作。必须指定以下选项之一:须指定以下选项之一:DO_NOTHING_ON_CLOSE(在(在WindowConstants中定义):不执行中定义):不执行任何操作;要求程序在已注册的任何操作;要求程序在已注册的WindowListener对象的对象的WindowClosing方法中处理该操作。方法中处理该操作。 HIDE_ON_CLOSE(在(在WindowConstants中定义):调用任意中定义):调用任意已注册的已注册的WindowListener对象后自动隐对象后自动隐藏该窗体。藏该窗体。DISPOSE_ON_CLOSE(在(在WindowConstants中定义):调用任意中定义):调用任意已注册已注册WindowListener的对象后自动隐的对象后自动隐藏并释放该窗体。藏并释放该窗体。EXIT_ON_CLOSE(在(在JFrame中定义):中定义):使用使用Systemexit方法退出应用程序。仅方法退出应用程序。仅在应用程序中使用。在应用程序中使用。 默认情况下,该值被设置为默认情况下,该值被设置为 HIDE_ON_CLOSE。JFrame(续)例如,在例如,在JFrame窗口上放置一个按钮。程窗口上放置一个按钮。程序主要代码如下:序主要代码如下:JFramejf=newJFrame(JFrame);/采用构造方法采用构造方法JFrame(Strings)JButtonjb=newJButton(JButton);/创建一个按钮创建一个按钮jf.setLayout(newFlowLayout();/布局方式,详见布局方式,详见7.3.3jf.add(jb);/将按钮放置在窗口中将按钮放置在窗口中jf.setBounds(50,50,150,80);/设设置窗口大小置窗口大小jf.setVisible(true);/设置窗口可见设置窗口可见 JDialogJDialog与与JFrame用法相同,只不过它用法相同,只不过它是设计对话框。一般而言对话框都会依是设计对话框。一般而言对话框都会依附在容器或对话框上,在使用上,附在容器或对话框上,在使用上,JDialog与与JFrame非常相似,由图非常相似,由图7.1可可以看出来,以看出来,JDialog是继承是继承AWT的的Dialog类而来,因此类而来,因此JDialog为一个重量为一个重量级组件。要将组件加入到级组件。要将组件加入到JDialog上其方上其方法与法与JFrame一样。一样。 JDialog(续) JDialog常用方法常用方法 :JDialog(Framef,Strings)创建一个具有标题的初始不可见的对创建一个具有标题的初始不可见的对话框,参数话框,参数s是标题的名字,是标题的名字,f是对话框是对话框所依赖的窗口所依赖的窗口JDialog(Framef,Strings,booleanb)创建一个具有标题创建一个具有标题s的初始不可见的的初始不可见的对话框。参数对话框。参数b决定对话框是否为有模式决定对话框是否为有模式或无模式,或无模式,,参数参数f是对话框所依赖的窗口是对话框所依赖的窗口getTitle()获取对话框的标题获取对话框的标题setTitle()设置对话框的标题设置对话框的标题setModal(booleanb)设置对话框的设置对话框的模式模式setSize()设置对话框的大小设置对话框的大小setVisible(booleanb)显示或隐藏对显示或隐藏对话框话框JDialog(续)例如,依赖上面所画例如,依赖上面所画JFrame窗体,对话窗体,对话框中放置一个按钮。程序主要代码如下:框中放置一个按钮。程序主要代码如下: JDialogd=newJDialog(jf,JDialog);/依赖窗体的对话依赖窗体的对话框框JButtonjb=newJButton(JButton);/创建一个按钮创建一个按钮d.setLayout(newFlowLayout();d.add(jb);/按钮加入对话框中按钮加入对话框中d.setSize(120,80);d.setVisible(true);JAppletJApplet用来设计可以在嵌入在网页中的用来设计可以在嵌入在网页中的Java小程序,具体内容在小程序,具体内容在8.3.4中介绍。中介绍。 中间容器在在Swing中,常用的中间容器有中,常用的中间容器有JPanel、JScrollPane、JToolBar和和JSplitPane等等 面板(JPanel)JPanel是在实际项目开发中使用频率最是在实际项目开发中使用频率最高的面板之一。高的面板之一。JPanel是一个轻量容器是一个轻量容器组件,用于容纳界面元素。组件,用于容纳界面元素。 JPanel常用方法常用方法 :JPanel()创建具有双缓冲和流布局的创建具有双缓冲和流布局的新新JPanelJPanel(LayoutManagerlayout)创建具有指定布局管理器的新缓冲创建具有指定布局管理器的新缓冲JPanelsetLayout(LayoutManagermgr)设置此容器的布局管理器。设置此容器的布局管理器。mgr为布为布局管理器局管理器setBounds(inta,intb,intwidth,intheight)移动组件并调整其大小。由移动组件并调整其大小。由x和和y指指定左上角的新位置,由定左上角的新位置,由width和和height指指定新的大小定新的大小setVisible(booleanb)根根据参数据参数b的值显示或隐藏此组件的值显示或隐藏此组件add(Componentcomp)将指定组件将指定组件comp追加到此容器的尾部追加到此容器的尾部滚动窗口(JScrollPane)JScrollPane是带滚动条的面板,可以用来显示文本、表格等内容。当内是带滚动条的面板,可以用来显示文本、表格等内容。当内容超过了容超过了JScrollPane面板的大小时,系统会自动添加滚动条。面板的大小时,系统会自动添加滚动条。JScrollPane常用方法常用方法 :JScrollPane()创建一个空的(无视口的视图)创建一个空的(无视口的视图)JScrollPane,需要时水,需要时水平和垂直滚动条都可显示平和垂直滚动条都可显示JScrollPane(intvsbPolicy,inthsbPolicy)创建一个具有指定滚动条策创建一个具有指定滚动条策略的空(无视口的视图)略的空(无视口的视图)JScrollPanecreateHorizontalScrollBar()默认返回水平的默认返回水平的JScrollPane.ScrollBarcreateVerticalScrollBar()默认返回垂直默认返回垂直的的JScrollPane.ScrollBarsetHorizontalScrollBarPolicy(inthsbpolicy)确定水平滚动条何时显示在滚动窗格上确定水平滚动条何时显示在滚动窗格上 setVerticalScrollBarPolicy(intvsbpolicy)确定垂直滚动条何时显示在确定垂直滚动条何时显示在滚动窗格上滚动窗格上setLayout(LayoutManagermgr)设置此容器的布局管理器。设置此容器的布局管理器。mgr为布局管理器为布局管理器滚动窗口(JScrollPane)setBounds(inta,intb,intwidth,intheight)移动组件并调整其大小。由移动组件并调整其大小。由a和和b指定左上角的新位置,由指定左上角的新位置,由width和和height指定新的大小指定新的大小setVisible(booleanb)根据参数根据参数b的值(的值(true或或false)显示或隐藏)显示或隐藏JScrollPaneadd(Componentcomp)将指定组件将指定组件comp追加到追加到JScrollPane.的尾部的尾部其中:参数其中:参数vsbpolicy和和hsbpolicy分别指定垂直滚动条策略和水平滚动分别指定垂直滚动条策略和水平滚动条策略的一个整数,其中条策略的一个整数,其中vsbpolicy选项有:选项有:ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDEDScrollPaneConstants.VERTICAL_SCROLLBAR_NEVERScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYShsbpolicy选项有:选项有: ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDEDScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVERScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS工具栏(JToolBar)JToolBar是用于放置各种常用的工具或控件组件。将一般常用的功能以是用于放置各种常用的工具或控件组件。将一般常用的功能以工具栏方式呈现在菜单下,可以提高用户的使用效率。工具栏方式呈现在菜单下,可以提高用户的使用效率。 JToolBar常用方法常用方法 :JToolBar()创建新的工具栏创建新的工具栏JToolBar(intorientation)创建具有指定创建具有指定orientation的新工具栏的新工具栏JToolBar(Stringname)创建名称为创建名称为name的工具栏,名称用作浮动式的工具栏,名称用作浮动式 (undocked)工具栏的标题。工具栏的标题。JToolBar(Stringname,intorientation)创建名称为创建名称为name、方向为、方向为orientation的工具栏的工具栏getComponentIndex(Componentc)返回指定组件的索引(从返回指定组件的索引(从0开始)开始),用于指示组件,用于指示组件c的位置的位置getComponentAtIndex(inti)得到一个指定索得到一个指定索引号的组件引号的组件其中,参数其中,参数orientation指工具栏的方向,其选项有指工具栏的方向,其选项有HORIZONTAL和和 VERTICAL两种,默认的方向为两种,默认的方向为HORIZONTAL。工具栏(JToolBar)例如,在滚动窗口中放置一个文本区组件,将其置于面板的正中间,面板上例如,在滚动窗口中放置一个文本区组件,将其置于面板的正中间,面板上方放置一具有三个按钮的工具栏。程序主要代码如下:方放置一具有三个按钮的工具栏。程序主要代码如下:/创建三个普通按钮组件创建三个普通按钮组件 JButtonbutton1=newJButton(图标一图标一);JButtonbutton2=newJButton(图标二图标二);JButtonbutton3=newJButton(图标三图标三);/创建一个工具条,再将上面创建的三个普通按钮组件添加到工具条中创建一个工具条,再将上面创建的三个普通按钮组件添加到工具条中 JToolBarbar=newJToolBar();bar.add(button1);bar.add(button2);bar.add(button3);JTextAreaedit=newJTextArea(8,40);/创建一个文本区组件创建一个文本区组件 JScrollPanescroller=newJScrollPane(edit);JPanelpane=newJPanel();BorderLayoutbord=newLayout();pane.setLayout(bord);/采用采用Border布局,参看布局,参看7.3.3布局管理器布局管理器 pane.add(North,bar);pane.add(Center,scroller);setContentPane(pane);分隔板(JSplitPane)JSplitPane面板用于分隔两个(只能两个)面板用于分隔两个(只能两个)组件,并且这两个组件可以由用户交互式调组件,并且这两个组件可以由用户交互式调整大小。整大小。JSplitPane常用方法常用方法 :JSplitPane()创建一个配置为将其子组件水创建一个配置为将其子组件水平排列、无连续布局、为组件使用两个按钮平排列、无连续布局、为组件使用两个按钮的新的新JSplitPanesetOneTouchExpandable(booleannewValue)设置设置oneTouchExpandable属性的值,属性的值,要使要使JSplitPane在分隔条上提供一个在分隔条上提供一个UI小部小部件来快速展开件来快速展开/折叠分隔条(比如箭头),折叠分隔条(比如箭头),此属性必须为此属性必须为truesetContinuousLayout(booleannewContinuousLayout)设置设置continuousLayout属属性的值,性的值,newContinuousLayout默认值为默认值为false,当为,当为true时,分隔条改变位置时组件时,分隔条改变位置时组件连续重绘连续重绘setOrientation(intorientation)设置方向或者分隔窗格的方式,参数设置方向或者分隔窗格的方式,参数orientation的选项有:的选项有: JSplitPane.VERTICAL_SPLIT(组件的上(组件的上/下方向)下方向) 和和JSplitPane.HORIZONTAL_SPLIT(组件的(组件的左左/右方向)两种右方向)两种setDividerLocation(intlocation)设置分隔设置分隔条的位置,条的位置,location指定特定于指定特定于UI值的一个值的一个整数(通常以像素为单位)整数(通常以像素为单位)分隔板(JSplitPane)setDividerSize(intnewSize)设置分隔条的大小,设置分隔条的大小,newSize给定分隔条大小的一个整数,以像素为单位给定分隔条大小的一个整数,以像素为单位setLeftComponent(Componentcomp)将组件将组件comp设置到分隔条的左边(或上面)设置到分隔条的左边(或上面)setRightComponent(Componentcomp)将组件将组件comp设置到分隔条的右边(或下面)设置到分隔条的右边(或下面)setPreferredSize(DimensionpreferredSize)设置此设置此组件的首选大小。如果组件的首选大小。如果preferredSize为新的首选大小,为新的首选大小,若为若为null,则要求,则要求UI提供首选大小,提供首选大小,Dimension类封类封装单个对象中组件的宽度和高度(精确到整数)装单个对象中组件的宽度和高度(精确到整数)例如,将例如,将JFrame窗口分成左右两个窗格,用两个标签窗口分成左右两个窗格,用两个标签分别指出分别指出“左窗格左窗格”和和“右窗格右窗格”。程序主要代码如。程序主要代码如下:下:分隔板(JSplitPane)JLabell1=newJLabel(左窗格左窗格);/创建两个标签组件创建两个标签组件JLabell2=newJLabel(右窗格右窗格);JSplitPanesp=newJSplitPane();/创建一个分隔板创建一个分隔板sp.setOneTouchExpandable(true);/让分割条显示出箭头让分割条显示出箭头sp.setContinuousLayout(true);/用户操作分割条箭头时,系统重用户操作分割条箭头时,系统重绘图形绘图形sp.setPreferredSize(newDimension(200,100);/设置尺寸设置尺寸sp.setOrientation(JSplitPane.HORIZONTAL_SPLIT);sp.setLeftComponent(l1);sp.setRightComponent(l2);sp.setDividerSize(3);/设分割条的粗细设分割条的粗细sp.setDividerLocation(100);/此处为此处为100/200,在中间位置,在中间位置JFramejf=newJFrame(JSplitPane);jf.add(sp);/将分割板加入窗体中将分割板加入窗体中jf.setVisible(true);jf.pack();/加载加载splitPane之后调用之后调用特殊容器特殊容器是在特殊容器是在GUI上起特殊作用的中间层,上起特殊作用的中间层,常见的有常见的有JLayeredPane、JInternalFrame和和JRootPane等等 分层面板(JLayeredPane)Swing提供两种分层面板:提供两种分层面板:JLayeredPane和和JDesktopPane。JLayeredPane为为JFC/Swing容器添加容器添加了深度,允许组件在需要时互相重叠;了深度,允许组件在需要时互相重叠;JDesktopPane是桌面窗格,用来实现是桌面窗格,用来实现桌面上内部窗体(桌面上内部窗体(JInternalFrame)的特)的特定界面样式行为。向一个分层面板中添定界面样式行为。向一个分层面板中添加组件时,需要指明将其加入哪一层,加组件时,需要指明将其加入哪一层,指明组件在该层中的位置。指明组件在该层中的位置。 JLayeredPane的常用方法的常用方法 :setLayer(Componentc,intlayer)设置设置指定组件指定组件c的的layer属性,使之成为该层属性,使之成为该层中最底部的组件。中最底部的组件。layer是指定的要设置是指定的要设置的层,值越小越接近底部。的层,值越小越接近底部。getLayer(Componentc)返回指定组返回指定组件件c当前层的当前层的int值值setPosition(Componentc,intposition)将该组件移到当前层中的将该组件移到当前层中的position处,处,其中其中0表示该层中的最顶层位置,表示该层中的最顶层位置,-1表示表示最底层位置最底层位置getLayeredPane()返回此内部窗体的返回此内部窗体的layeredPane对象对象getLayeredPane()获得分层面板获得分层面板setLayeredPane(JlayeredPanelp)设设置分层面板置分层面板分层面板(JLayeredPane)例如,在窗口中添加两个按钮,利用分层面板,将两个按钮进行重叠,例如,在窗口中添加两个按钮,利用分层面板,将两个按钮进行重叠,程序的主要代码如下:程序的主要代码如下:JLayeredPanelp=this.getLayeredPane();/要用到的层要用到的层,获取获取JLayeredPaneJButtonJLP_a=newJButton(A);JButtonJLP_b=newJButton(B);lp.setLayer(JLP_a,200);/将组件添加到将组件添加到JLayeredPane中,指定所在中,指定所在的层的层lp.add(JLP_a);lp.setLayer(JLP_b,300);lp.add(JLP_b);JLP_a.setBounds(newRectangle(100,100,100,100);/Button出现位出现位置置JLP_b.setBounds(newRectangle(50,50,100,100);内部框架(JInternalFrame)内部框架内部框架JInternalFrame的使用与的使用与JFrame几乎一样,可以最大化、最小化、几乎一样,可以最大化、最小化、关闭窗口、加入菜单等功能,唯一不同关闭窗口、加入菜单等功能,唯一不同的是的是JInternalFrame不能单独出现,通不能单独出现,通常加入到桌面窗格(常加入到桌面窗格(JDesktopPane)中,)中,从而方便管理。其中从而方便管理。其中JDesktopPane是是一种特殊的分层面板(一种特殊的分层面板(JLayeredPane),),用来创建虚拟桌面(用来创建虚拟桌面(VirtualDesktop),),它可以显示并管理众多的它可以显示并管理众多的JInternalFrame之间的层次关系。之间的层次关系。内部框架(JInternalFrame) JInternalFrame构造方法构造方法 :JInternalFrame()创建不可调整大小的、不可关闭的、不可最大化的、创建不可调整大小的、不可关闭的、不可最大化的、不可图标化的、没有标题的不可图标化的、没有标题的JInternalFrameJInternalFrame(Stringtitle)创建不可调整大小的、不可关闭的、不可创建不可调整大小的、不可关闭的、不可最大化的、不可图标化的、具有指定标题的最大化的、不可图标化的、具有指定标题的JInternalFrameJInternalFrame(Stringtitle,booleanresizable)创建不可关闭的、不可创建不可关闭的、不可最大化的、不可图标化的,以及具有指定标题和可调整大小的最大化的、不可图标化的,以及具有指定标题和可调整大小的JInternalFrameJInternalFrame(Stringtitle,booleanresizable,booleanclosable)创创建不可最大化的、不可图标化的,以及具有指定标题、可调整大小和可建不可最大化的、不可图标化的,以及具有指定标题、可调整大小和可关闭的关闭的JInternalFrameJInternalFrame(Stringtitle,booleanresizable,booleanclosable,booleanmaximizable)创建不可图标化的,但具有指定标题、可调整大创建不可图标化的,但具有指定标题、可调整大小、可关闭和可最大化的小、可关闭和可最大化的JInternalFrameJInternalFrame(Stringtitle,booleanresizable,booleanclosable,booleanmaximizable,booleaniconifiable)创建具有指定标题、可调创建具有指定标题、可调整、可关闭、可最大化和可图标化的整、可关闭、可最大化和可图标化的JInternalFrame内部框架(JInternalFrame)例如,创建两个例如,创建两个JInternalFrame窗口,窗口,将这两个窗口放到一个顶层容器中。将这两个窗口放到一个顶层容器中。JFramejf=newJFrame(JInternalFrame);jf.setSize(300,150);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);JPanelcontentPane=newJPanel();/*创建一个面板,并且将之添创建一个面板,并且将之添加到顶层容器内,将之设置为流布局加到顶层容器内,将之设置为流布局* */jf.setContentPane(contentPane);contentPane.setLayout(newFlowLayout();JDesktopPanedp=newJDesktopPane();/*创建一个虚拟桌面容创建一个虚拟桌面容器,将器,将dp添加到以上创建的中间容器中添加到以上创建的中间容器中* */dp.setLayout(newFlowLayout();contentPane.add(dp);JInternalFramejif=newJInternalFrame(第一个窗口第一个窗口,true,true,true);内部框架(JInternalFrame)/*创建两个创建两个JIntenaFrame容器,并且创容器,并且创建六个标签组件,分别将它们添加到两建六个标签组件,分别将它们添加到两个个JInternaFrame容器内容器内* */JInternalFramejif1=newJInternalFrame(第二个窗口第二个窗口,true,true,true);JLabell1=newJLabel(这是第一个这是第一个窗口窗口);JLabell4=newJLabel(这是第二个这是第二个窗口窗口);jif.setLayout(newFlowLayout();jif1.setLayout(newFlowLayout();jif.add(l1);jif1.add(l4);dp.add(jif);dp.add(jif1);jif.setVisible(true);jif1.setVisible(true);根面板(JRootPane)JRootPane面板是由许多部分组成的,面板是由许多部分组成的,它可以直接从顶层容器中获得一个它可以直接从顶层容器中获得一个JRootPane对象直接使用,而不需要创对象直接使用,而不需要创建新对象。建新对象。JRootPane面板由一个玻璃面板由一个玻璃面板(面板(GlassPane)和一个分层面板)和一个分层面板(JLayeredPane)组成。其中分层面板)组成。其中分层面板是由内容面板(是由内容面板(ContentPane)和一个可)和一个可选择的菜单条(选择的菜单条(JMenuBar)组成。玻璃)组成。玻璃面板是完全透明的,缺省为不可见,为面板是完全透明的,缺省为不可见,为接收鼠标事件或在所有组件上绘图提供接收鼠标事件或在所有组件上绘图提供方便。实际上方便。实际上JRootPane只是一个容器,只是一个容器,是一个可以装载其他容器类的容器,它是一个可以装载其他容器类的容器,它可以装载菜单、内容面板或其他容器等。可以装载菜单、内容面板或其他容器等。JLayeredPane为为Swing容器添加了深度,容器添加了深度,允许组件在需要时互相重叠。为方便起允许组件在需要时互相重叠。为方便起见,见,JLayeredPane将该深度范围分成几将该深度范围分成几个不同的层,将组件放入相应的层,更个不同的层,将组件放入相应的层,更容易确保组件正确地重叠。容易确保组件正确地重叠。 根面板(JRootPane)JRootPane常用方法常用方法 :getContentPane()获得内容面板获得内容面板setContentPane(Containercon)设置设置内容面板内容面板getMenuBar()活动菜单条活动菜单条setMenuBar(JMenuBarmenubar)设置设置菜单条菜单条getGlassPane()获得玻璃面板获得玻璃面板setGlassPane(Componentc)设置玻璃设置玻璃面板面板布局管理器所谓布局管理器,就是为容器内的组件所谓布局管理器,就是为容器内的组件提供若干布局策略,每个容器都拥有某提供若干布局策略,每个容器都拥有某种默认的布局管理器,用于负责其内部种默认的布局管理器,用于负责其内部组件的排列。目前常用有组件的排列。目前常用有FlowLayout、BorderLayout、GridLayout、CardLayout、GridBagLayout、BoxLayout等布局。其中前等布局。其中前5种布局均由种布局均由AWT包提供,包提供,Swing新增加了新增加了BoxLayout布局,其显示效果与布局,其显示效果与AWT略略有不同。有不同。 FlowLayout布局管理器FlowLayout(流布局或顺序布局管理器)(流布局或顺序布局管理器)是最简单的布局。它的排版原则是将组是最简单的布局。它的排版原则是将组件从左向右,从上向下排列,默认情况件从左向右,从上向下排列,默认情况下每一行的组件都是居中排列。下每一行的组件都是居中排列。FlowLayout是是JPanel和和JApplet缺省的缺省的布局方式。布局方式。FlowLayout布局效果如图所示。布局效果如图所示。FlowLayout布局管理器(续) FlowLayout常用方法常用方法 :FlowLayout()构造一个新的构造一个新的 FlowLayout,居中对齐,默认的水平和垂,居中对齐,默认的水平和垂直间隙是直间隙是5个单位个单位FlowLayout(intalign)构造一个新的构造一个新的FlowLayout,对齐方式是指定的,对齐方式是指定的,默认的水平和垂直间隙是默认的水平和垂直间隙是5个单位个单位FlowLayout(intalign,inthgap,intvgap)创建一个新的流布局管理器,创建一个新的流布局管理器,具有指定的对齐方式以及指定的水平和垂直间隙具有指定的对齐方式以及指定的水平和垂直间隙getAlignment()获得此布局的对齐方式获得此布局的对齐方式getHgap()获得组件之间以及组件与容器的边之间的水平间隙获得组件之间以及组件与容器的边之间的水平间隙getVgap()获得组件之间以及组件与容器的边之间的水平间隙获得组件之间以及组件与容器的边之间的水平间隙setAlignment(intalign)设置此布局的对齐方式设置此布局的对齐方式setHgap(inthgap)设置组件之间以及组件与容器的边之间的水平间隙设置组件之间以及组件与容器的边之间的水平间隙setVgap(intvgap)设置组件之间以及组件与容器的边之间的水平间隙设置组件之间以及组件与容器的边之间的水平间隙FlowLayout布局管理器(续)其中参数其中参数align是对齐方式,其值有是对齐方式,其值有FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING或或FlowLayout.TRAILING;参数;参数hgap是组件之间以及组件与容器的边是组件之间以及组件与容器的边之间的水平间隙;参数之间的水平间隙;参数vgap是组件之间以及组件与容器的边之间的垂直是组件之间以及组件与容器的边之间的垂直间隙。其他布局方式的方法中相同参数属性相同。间隙。其他布局方式的方法中相同参数属性相同。采用采用setLayout(LayoutManagermgr)方法设置组件容器采用的布局方方法设置组件容器采用的布局方式式例如,采用流布局,对齐方式为左对齐的语句如下:例如,采用流布局,对齐方式为左对齐的语句如下:setLayout(newFlowLayout(FlowLayout.LEFT);此外,此外,FlowLayout中还可以设置横向和纵向的间隔,设置间隔可以使用中还可以设置横向和纵向的间隔,设置间隔可以使用下面的语句:下面的语句:例如,将横向和纵向间隔设置成例如,将横向和纵向间隔设置成10像素的语句如下:像素的语句如下: setLayout(newFlowLayout(FlowLayout.CENTER,10,10);BorderLayout布局管理器BorderLayout是一种简单的布局,该布是一种简单的布局,该布局把容器分为上(局把容器分为上(North)、下)、下(South)、左()、左(West)、右()、右(East)、)、中间(中间(Center)5个区域,每个组件将占个区域,每个组件将占据每个区域。其中前据每个区域。其中前4个方向占据屏幕的个方向占据屏幕的四边,而四边,而Center方向占据中间剩下的空方向占据中间剩下的空白。白。 这种布局一般用于给自己定义的这种布局一般用于给自己定义的JPanel添加边框。添加边框。BorderLayout是是JFrame和和JDialog缺省的布局。缺省的布局。BorderLayout布局效果如图所示。布局效果如图所示。BorderLayout常用方法:常用方法:BorderLayout()构造一个组件之间没有间距的新边界布局构造一个组件之间没有间距的新边界布局BorderLayout(inthgap,intvgap)用指定的组件之间的水平间距构造用指定的组件之间的水平间距构造一个边界布局一个边界布局setHgap(inthgap)设置组件之间的水平间距设置组件之间的水平间距setVgap(intvgap)设置组件之间的垂直间距设置组件之间的垂直间距getVgap()返回组件之间的垂直间距返回组件之间的垂直间距getHgap()返回组件之间的水平间距返回组件之间的水平间距例如,采用例如,采用BorderLayout布局,并将按钮放在窗口上方的语句如下:布局,并将按钮放在窗口上方的语句如下:setLayout(newBorderLayout();JButtonb=newJButton(Button);add(b,BorderLayout.NORTH);BorderLayout布局管理器布局管理器GridLayout布局管理器GridLayout有点像围棋盘,将布局空间有点像围棋盘,将布局空间划分成若干行若干列的网格区域。添加划分成若干行若干列的网格区域。添加的组件就在这些小的网格区域内。的组件就在这些小的网格区域内。GridLayout布局效果如图所示。布局效果如图所示。GridLayout布局管理器(续)GridLayout常用方法常用方法 :GridLayout()创建具有默认值的网格布局,即每个组件占据一行一列创建具有默认值的网格布局,即每个组件占据一行一列GridLayout(introws,intcols)创建具有指定行数和列数的网格布局创建具有指定行数和列数的网格布局GridLayout(introws,intcols,inthgap,intvgap)创建具有指定行数创建具有指定行数 rows和列数和列数cols的网格布局的网格布局setColumns(intcols)将此布局中的列数设置为指定值将此布局中的列数设置为指定值colssetHgap(inthgap)将组件之间的水平间距设置为指定值将组件之间的水平间距设置为指定值setRows(introws)将此布局中的行数设置为指定值将此布局中的行数设置为指定值rowssetVgap(intvgap)将组件之间的垂直间距设置为指定值将组件之间的垂直间距设置为指定值getColumns()获取此布局中的列数获取此布局中的列数getHgap()获取组件之间的水平间距获取组件之间的水平间距getRows()获取此布局中的行数获取此布局中的行数getVgap()获取组件之间的垂直间距获取组件之间的垂直间距GridLayout布局管理器(续)例如,采用例如,采用GridLayout布局,设置一行布局,设置一行两列,放置两个按钮的语句如下:两列,放置两个按钮的语句如下:setLayout(newGridLayout(1,2);JButtonb1=newJButton(Button1);JButtonb2=newJButton(Button2);add(b1);add(b2);CardLayout布局管理器CardLayout将容器中的每个组件当作一将容器中的每个组件当作一张卡片,在一个容器中可以加入多个卡张卡片,在一个容器中可以加入多个卡片,但每次只有一个卡片是可见的。片,但每次只有一个卡片是可见的。 CardLayout常用方法常用方法 :CardLayout()创建一个间隙大小为创建一个间隙大小为0的的新卡片布局新卡片布局CardLayout(inthgap,intvgap)创建一创建一个具有指定的水平和垂直间隙的新卡片个具有指定的水平和垂直间隙的新卡片布局布局addLayoutComponent(Componentcomp,Objectconstraints)将指定的组件将指定的组件添加到此卡片布局的内部名称表。其中添加到此卡片布局的内部名称表。其中参数参数comp是要添加的组件;参数是要添加的组件;参数constraints是标识布局中特定卡片的标是标识布局中特定卡片的标记记setHgap(inthgap)设置组件之间的水平设置组件之间的水平间隙间隙setVgap(intvgap)设置组件之间的垂直设置组件之间的垂直间隙间隙previous(Containerparent)翻转翻转到指定容器到指定容器parent的前一张卡片的前一张卡片next(Containerparent)翻转到指定容器翻转到指定容器parent的下一张卡片的下一张卡片last(Containerparent)翻转到容器翻转到容器 parent的最后一张卡片的最后一张卡片first(Containerparent)翻转到容器翻转到容器 parent的第一张卡片的第一张卡片CardLayout布局管理器(续)getHgap()获得组件之间的水平间隙获得组件之间的水平间隙getLayoutAlignmentX(Containerparent)返回容器返回容器 parent中组件沿中组件沿x轴的对齐轴的对齐方式。返回值应该在方式。返回值应该在0和和1之间,其中之间,其中0表表示根据原点进行对齐,示根据原点进行对齐,1表示根据距离原表示根据距离原点最远的点对齐,点最远的点对齐,0.5表示居中对齐等。表示居中对齐等。getLayoutAlignmentY(Containerparent)返回容器返回容器 parent中组件沿中组件沿y轴的对齐轴的对齐方式。返回值应该在方式。返回值应该在0和和1之间,其中之间,其中0表表示根据原点进行对齐,示根据原点进行对齐,1表示根据距离原表示根据距离原点最远的点对齐,点最远的点对齐,0.5表示居中对齐等等。表示居中对齐等等。getVgap()获得组件之间的垂直间隙获得组件之间的垂直间隙例如,采用例如,采用CardLayout布局,将两个按钮放在卡片中的语句如下:布局,将两个按钮放在卡片中的语句如下:JButtonb1=newJButton(First);JButtonb2=newJButton(Last);setLayout(newCardLayout();add(b1,1);add(b2,2);GridBagLayout布局管理器GridBagLayout是一种非常灵活的布局,是一种非常灵活的布局,也是最复杂的。它是在将屏幕划分成网也是最复杂的。它是在将屏幕划分成网格的基础上,允许每个组件占据一个或格的基础上,允许每个组件占据一个或多个区域。与多个区域。与GridLayout不同,不同,GridBagLayout是按照开发人员自己的是按照开发人员自己的需要安排组件位置。需要安排组件位置。GridBagLayout布局效果如图所示。布局效果如图所示。GridBagLayout布局管理器(续) GridBagLayout常用方法常用方法 :GridBagLayout()创建网格包布局管理器创建网格包布局管理器arrangeGrid(Containerparent)布置网格。其中参数布置网格。其中参数parent是布局容是布局容器器addLayoutComponent(Componentcomp,Objectconstraints)使用指定使用指定 constraints对象将指定组件添加到布局对象将指定组件添加到布局中。其中参数中。其中参数constraints是确定如何将组件添加到布局的对象是确定如何将组件添加到布局的对象getConstraints(Componentcomp)获取指定组件的约束。返回实际获取指定组件的约束。返回实际GridBagConstraints对象的副本对象的副本getLayoutDimensions()确定布局网格的列宽度和行高度确定布局网格的列宽度和行高度,大多数应用程大多数应用程序并不直接调用此方法序并不直接调用此方法setConstraints(Componentcomp,GridBagConstraintsconstraints)设置此布局中指定组件的约束条件设置此布局中指定组件的约束条件constraints其中参数其中参数comp是制定的组件。是制定的组件。GridBagLayout布局管理器(续)GridBagLayout需要创建约束对需要创建约束对象象GridBagConstraints,GridBagConstraints类指定使用类指定使用GridBagLayout类布置的组件的类布置的组件的约束。约束。GridBagConstraints的常用参数的常用参数参数意义gridx组件的横向坐标girdy组件的纵向坐标gridwidth组件的横向宽度,也就是指组件占用的列数。使用RELATIVE指定组件的显示区域从gridx到它所在行的倒数第二个单元格;使用REMAINDER指定组件的显示区域为从gridx到该行(针对gridwidth)中的最后一个单元gridheight组件的纵向长度,也就是指组件占用的行数weightx指行的权重,告诉布局管理器如何分配额外的水平空间weighty指列的权重,告诉布局管理器如何分配额外的垂直空间anchor当组件小于其显示区域时使用此属性fill如果显示区域比组件的区域大的时候,可以用来控制组件的行为。控制组件是垂直填充,还是水平填充,或者两个方向一起填充insets指组件与表格空间四周边缘的空白区域的大小ipadx组件间的横向间距,组件的宽度就是这个组件的最小宽度加上ipadx值ipady组件间的纵向间距,组件的高度就是这个组件的最小高度加上ipady值GridBagLayout布局管理器(续)例如,采用例如,采用GridBagLayout布局,在窗布局,在窗体上放置体上放置b1-b5共五个按钮。共五个按钮。b1、b2和和b3位于第一行,填充整个区域;后两个位于第一行,填充整个区域;后两个按钮位于第二行,其中按钮位于第二行,其中b4按钮占据两个按钮占据两个按钮的位置的主要代码如下:按钮的位置的主要代码如下:JFramef=newJFrame(GridBagLayout);GridBagLayoutgridbag=newGridBagLayout();GridBagConstraintsc=newGridBagConstraints();f.setLayout(gridbag);c.fill=GridBagConstraints.BOTH;/使使组件完全填满其显示区域组件完全填满其显示区域c.weightx=1.0;/分布额外的分布额外的水平空间水平空间gridbag.setConstraints(b1,c);/指定按钮指定按钮b1的约束条件为的约束条件为cgridbag.setConstraints(b2,c);GridBagLayout布局管理器(续)c.gridwidth=GridBagConstraints.REMAINDER;/*组件的显示区域为从组件的显示区域为从gridx到该行到该行(针对针对gridwidth)中的最后一个单元)中的最后一个单元* */c.weightx=0.0;gridbag.setConstraints(b3,c);c.weightx=0.0;c.gridwidth=GridBagConstraints.RELATIVE;/指定指定组件为其行中的倒数第二个组件组件为其行中的倒数第二个组件gridbag.setConstraints(b4,c);c.gridwidth=GridBagConstraints.REMAINDER;gridbag.setConstraints(b5,c);BoxLayout布局管理器BoxLayout(盒式布局或箱式布局)与前面几种布局不同的是(盒式布局或箱式布局)与前面几种布局不同的是BoxLayout是由是由Swing提供的布局方式,功能上同提供的布局方式,功能上同GridBagLayout一样一样强大,而且更加易用。强大,而且更加易用。BoxLayout将几个组件以水平或垂直的方式组合将几个组件以水平或垂直的方式组合在一起,其中各个组件的大小随窗口的大小变化而变化。在一起,其中各个组件的大小随窗口的大小变化而变化。 BoxLayout常用方法常用方法 :BoxLayout(Containertarget,intaxis)创建一个将沿给定轴放置组件的创建一个将沿给定轴放置组件的布局管理器,布局管理器,target是需要布置的容器,参数是需要布置的容器,参数axis是布置组件时使用的是布置组件时使用的轴。它可以是以下值之一:轴。它可以是以下值之一:BoxLayout.X_AXIS、BoxLayout.Y_AXIS、BoxLayout.LINE_AXIS或或 BoxLayout.PAGE_AXIScreateGlue()创建一个不可见的创建一个不可见的“glue”组件,在其可见组件有一个最组件,在其可见组件有一个最大宽度(对于横向大宽度(对于横向box)或高度(对于纵向)或高度(对于纵向box)的)的Box中,该组件可能中,该组件可能很有用很有用createHorizontalBox()创建一个从左到右显示其组件的创建一个从左到右显示其组件的BoxcreateHorizontalGlue()创建一个横向创建一个横向glue组件组件createHorizontalStrut(intwidth)创建一个不可见的、固定宽度为创建一个不可见的、固定宽度为width的组件的组件BoxLayout布局管理器(续)createVerticalBox()创建一个从上到下显示其组件的创建一个从上到下显示其组件的BoxcreateVerticalGlue()创建一个纵向创建一个纵向glue组件组件createVerticalStrut(intheight)创建一个不可见的、固定高度创建一个不可见的、固定高度height的的组件组件getAccessibleContext()获得与此获得与此Box相关联的相关联的AccessibleContext例如,采用例如,采用BoxLayout布局的语句,并将两个按钮水平从上到下放于一布局的语句,并将两个按钮水平从上到下放于一列的主要代码如下:列的主要代码如下:Containerc=this.getContentPane();/需要布置的容器需要布置的容器BoxLayoutbox1=newBoxLayout(c,BoxLayout.Y_AXIS);/指定按钮从上到下放置指定按钮从上到下放置c.setLayout(box1);/设置布局方式为设置布局方式为BoxLayout布局布局 c.add(newJButton(first);c.add(Box.createVerticalStrut(10);/创建一个不可见的、固定高创建一个不可见的、固定高度的空间量度的空间量c.add(newJButton(second);本章小结抽象窗口工具包(抽象窗口工具包(AbstractWindowtoolkit,AWT)提供了一套与本)提供了一套与本地图形界面进行交互的接口。地图形界面进行交互的接口。AWT中的图形函数与操作系统所提供的图中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,称之为形函数之间有着一一对应的关系,称之为peers。当利用。当利用AWT来构建图来构建图形用户界面时,实际上是在利用操作系统所提供的图形库,但是不同操形用户界面时,实际上是在利用操作系统所提供的图形库,但是不同操作系统的图形库所提供的功能不一样,在一个平台上存在的功能在另外作系统的图形库所提供的功能不一样,在一个平台上存在的功能在另外一个平台上则可能不存在,所以为了实现一个平台上则可能不存在,所以为了实现Java语言所宣称的语言所宣称的“一次编译,一次编译,到处运行到处运行”,AWT不得不通过牺牲功能来实现其平台无关性,也就是说,不得不通过牺牲功能来实现其平台无关性,也就是说,AWT所提供的图形功能是各种通用型操作系统所提供的图形功能的交集。所提供的图形功能是各种通用型操作系统所提供的图形功能的交集。由于由于AWT是依靠本地方法来实现其功能的,通常把是依靠本地方法来实现其功能的,通常把AWT组件称为重量级组件称为重量级组件。组件。AWT是是Java最早用于编写图形界面应用程序的开发包。最早用于编写图形界面应用程序的开发包。Swing是在是在AWT的基础上构建的一套新的图形界面系统,它提供了的基础上构建的一套新的图形界面系统,它提供了AWT所能够提供的所有功能,并且用纯粹的所能够提供的所有功能,并且用纯粹的Java代码对代码对AWT的功能进行了大的功能进行了大幅度的扩充。由于在幅度的扩充。由于在Swing中没有使用本地方法来实现图形功能,通常中没有使用本地方法来实现图形功能,通常把把Swing组件称为轻量级组件。组件称为轻量级组件。 本章小结(续)AWT是基于本地方法的是基于本地方法的C/C+程序,其运行速度比较快;程序,其运行速度比较快;Swing是基于是基于AWT的的Java程序,其运行速度比较慢。对于一个嵌入式应用来说,目标程序,其运行速度比较慢。对于一个嵌入式应用来说,目标平台的硬件资源往往非常有限,而应用程序的运行速度又是项目中至关平台的硬件资源往往非常有限,而应用程序的运行速度又是项目中至关重要的因素。在这种矛盾的情况下,简单而高效的重要的因素。在这种矛盾的情况下,简单而高效的AWT当然成了嵌入式当然成了嵌入式Java的第一选择;而在普通的基于的第一选择;而在普通的基于PC或者是工作站的标准或者是工作站的标准Java应用中,应用中,硬件资源对应用程序所造成的限制往往不是项目中的关键因素,所以在硬件资源对应用程序所造成的限制往往不是项目中的关键因素,所以在标准版的标准版的Java中则提倡使用中则提倡使用Swing,也就是通过牺牲速度来实现应用程,也就是通过牺牲速度来实现应用程序的功能。序的功能。容器从功能上可分为顶层容器、中间容器和特殊容器三种。容器从功能上可分为顶层容器、中间容器和特殊容器三种。开发人员在使用开发人员在使用Java进行图形编程时,其组件需要放置在能够提供图进行图形编程时,其组件需要放置在能够提供图形绘制的容器中,这样的容器就是顶层容器,也可以认为是一个窗口。形绘制的容器中,这样的容器就是顶层容器,也可以认为是一个窗口。在在Swing中,有中,有JFrame、JDialog和和JApplet三种常用的顶层容器。三种常用的顶层容器。JFrame用来设计类似于用来设计类似于Windows系统中的窗口形式的应用程序。系统中的窗口形式的应用程序。JDialog与与JFrame用法相同,只不过它是设计对话框。用法相同,只不过它是设计对话框。JApplet用来设计可以在嵌入在网页中的用来设计可以在嵌入在网页中的Java小程序。小程序。本章小结(续)要想得到丰富多彩的要想得到丰富多彩的Java用户界面,用户界面,就要用到面板,它们都属于中间容器。就要用到面板,它们都属于中间容器。可以将面板添加到顶层容器中,也可以可以将面板添加到顶层容器中,也可以将下一级面板依次添加到上一级面板中。将下一级面板依次添加到上一级面板中。在在Swing中,常用的中间容器有中,常用的中间容器有JPanel、JScrollPane、JToolBar和和JSplitPane等。等。JPanel是在实际项目开发中使用频率最是在实际项目开发中使用频率最高的面板之一。高的面板之一。JPanel是一个轻量容器是一个轻量容器组件,用于容纳界面元素。组件,用于容纳界面元素。JScrollPane是带滚动条的面板,可以是带滚动条的面板,可以用来显示文本、表格等内容。当内容超用来显示文本、表格等内容。当内容超过了过了JScrollPane面板的大小时,系统会面板的大小时,系统会自动添加滚动条。自动添加滚动条。JToolBar是用于放置各种常用的工具或是用于放置各种常用的工具或控件组件。将一般常用的功能以工具栏控件组件。将一般常用的功能以工具栏方式呈现在菜单下,可以提高用户的使方式呈现在菜单下,可以提高用户的使用效率。用效率。JSplitPane面板用于分隔两个(只能两面板用于分隔两个(只能两个)组件,并且这两个组件可以由用户个)组件,并且这两个组件可以由用户交互式调整大小。交互式调整大小。本章小结(续)特殊容器是在特殊容器是在GUI上起特殊作用的中间层,常见的有上起特殊作用的中间层,常见的有JLayeredPane、JInternalFrame和和JRootPane等。等。Swing提供两种分层面板:提供两种分层面板:JLayeredPane和和JDesktopPane。JLayeredPane为为JFC/Swing容器添加了深度,允许组件在需要时互相容器添加了深度,允许组件在需要时互相重叠;重叠;JDesktopPane是桌面窗格,用来实现桌面上内部窗体是桌面窗格,用来实现桌面上内部窗体(JInternalFrame)的特定界面样式行为。向一个分层面板中添加组件)的特定界面样式行为。向一个分层面板中添加组件时,需要指明将其加入哪一层,指明组件在该层中的位置。时,需要指明将其加入哪一层,指明组件在该层中的位置。内部框架内部框架JInternalFrame的使用与的使用与JFrame几乎一样,可以最大化、最几乎一样,可以最大化、最小化、关闭窗口、加入菜单等功能,唯一不同的是小化、关闭窗口、加入菜单等功能,唯一不同的是JInternalFrame不能不能单独出现,通常加入到桌面窗格(单独出现,通常加入到桌面窗格(JDesktopPane)中,从而方便管理。)中,从而方便管理。其中其中JDesktopPane是一种特殊的分层面板(是一种特殊的分层面板(JLayeredPane),用来创),用来创建虚拟桌面(建虚拟桌面(VirtualDesktop),它可以显示并管理众多的),它可以显示并管理众多的JInternalFrame之间的层次关系。之间的层次关系。本章小结(续)JRootPane面板是由许多部分组成的,它可以直接从顶层容器中获得一面板是由许多部分组成的,它可以直接从顶层容器中获得一个个JRootPane对象直接使用,而不需要创建新对象。对象直接使用,而不需要创建新对象。JRootPane面板由面板由一个玻璃面板(一个玻璃面板(GlassPane)和一个分层面板()和一个分层面板(JLayeredPane)组成。其)组成。其中分层面板是由内容面板(中分层面板是由内容面板(ContentPane)和一个可选择的菜单条)和一个可选择的菜单条(JMenuBar)组成。玻璃面板是完全透明的,缺省为不可见,为接收鼠)组成。玻璃面板是完全透明的,缺省为不可见,为接收鼠标事件或在所有组件上绘图提供方便。实际上标事件或在所有组件上绘图提供方便。实际上JRootPane只是一个容器,只是一个容器,是一个可以装载其他容器类的容器,它可以装载菜单、内容面板或其他是一个可以装载其他容器类的容器,它可以装载菜单、内容面板或其他容器等。容器等。在实际编程中,每设计一个窗体,都要往其中添加若干组件。为了管在实际编程中,每设计一个窗体,都要往其中添加若干组件。为了管理好这些组件的布局,就需要使用布局管理器。目前常用有理好这些组件的布局,就需要使用布局管理器。目前常用有FlowLayout、BorderLayout、GridLayout、CardLayout、GridBagLayout、BoxLayout等布局。其中前等布局。其中前5种布局均由种布局均由AWT包提供,包提供,Swing新增加了新增加了BoxLayout布局,其显示效果与布局,其显示效果与AWT略有不同。略有不同。本章小结(续)FlowLayout(流布局或顺序布局管理器)是最简单的布局。它的排版原则是将(流布局或顺序布局管理器)是最简单的布局。它的排版原则是将组件从左向右,从上向下排列,默认情况下每一行的组件都是居中排列。组件从左向右,从上向下排列,默认情况下每一行的组件都是居中排列。FlowLayout是是JApplet缺省的布局方式。缺省的布局方式。BorderLayout是一种简单的布局,该布局把容器分为上(是一种简单的布局,该布局把容器分为上(North)、下)、下(South)、左()、左(West)、右()、右(East)、中间()、中间(Center)5个区域,每个组件将占个区域,每个组件将占据每个区域。其中前据每个区域。其中前4个方向占据屏幕的四边,而个方向占据屏幕的四边,而Center方向占据中间剩下的空方向占据中间剩下的空白。白。GridLayout有点像围棋盘,将布局空间划分成若干行若干列的网格区域。添加的有点像围棋盘,将布局空间划分成若干行若干列的网格区域。添加的组件就在这些小的网格区域内。组件就在这些小的网格区域内。CardLayout将容器中的每个组件当作一张卡片,在一个容器中可以加入多个卡将容器中的每个组件当作一张卡片,在一个容器中可以加入多个卡片,但每次只有一个卡片是可见的。片,但每次只有一个卡片是可见的。GridBagLayout是一种非常灵活的布局,也是最复杂的。它是在将屏幕划分成网是一种非常灵活的布局,也是最复杂的。它是在将屏幕划分成网格的基础上,允许每个组件占据一个或多个区域。与格的基础上,允许每个组件占据一个或多个区域。与GridLayout不同,不同,GridBagLayout是按照开发人员自己的需要安排组件位置。是按照开发人员自己的需要安排组件位置。BoxLayout是由是由Swing提供的布局方式,功能上同提供的布局方式,功能上同GridBagLayout一样强大,而一样强大,而且更加易用。且更加易用。BoxLayout将几个组件以水平或垂直的方式组合在一起,其中各个将几个组件以水平或垂直的方式组合在一起,其中各个组件的大小随窗口的大小变化而变化。组件的大小随窗口的大小变化而变化。Java程序设计基础与实践 第8章图形界面常用组件应用本章要点Java事件处理机制事件处理机制JavaSwing常用组件及组件事件处理方常用组件及组件事件处理方法法JavaApplet程序程序图形界面的绘制方法图形界面的绘制方法Java事件处理机制Java事件处理流程事件处理流程事件源事件源能够产生事件的对象都可以成为事件源,如按钮、文本框等。换句话说,事能够产生事件的对象都可以成为事件源,如按钮、文本框等。换句话说,事件源必须是一个对象,而且该对象必须是件源必须是一个对象,而且该对象必须是Java认为能够发生事件的对象。认为能够发生事件的对象。监视器监视器监视器就是一个对事件源进行监视的对象,事件源通过调用相应的方法将某监视器就是一个对事件源进行监视的对象,事件源通过调用相应的方法将某个对象作为自己的监视器。事件源是不处理事件的,而是将事件转交给监视个对象作为自己的监视器。事件源是不处理事件的,而是将事件转交给监视器来处理。器来处理。处理事件的接口处理事件的接口监视器是一个对象,为了处理事件源发生的事件,它会自动调用它所属类中监视器是一个对象,为了处理事件源发生的事件,它会自动调用它所属类中的方法来处理事件。的方法来处理事件。Java规定,为了让监视器对象能对事件源发生的事件进规定,为了让监视器对象能对事件源发生的事件进行处理,创建该监视器对象的类必须声明实现相应的接口,即必须在类体中行处理,创建该监视器对象的类必须声明实现相应的接口,即必须在类体中给出该接口中所有方法的方法体,那么当事件源发生事件时,监视器对象就给出该接口中所有方法的方法体,那么当事件源发生事件时,监视器对象就会自动调用类中已实现的接口方法来处理事件。会自动调用类中已实现的接口方法来处理事件。Java事件处理机制(续)javax.swing.event包中提供了许多事件类包中提供了许多事件类和处理各种事件的接口。对于按钮,事件和处理各种事件的接口。对于按钮,事件最基本的处理过程如下:最基本的处理过程如下:引入事件包引入事件包importjavax.swing.event.*;定义实现事件监视器接口定义实现事件监视器接口classActionHandlerimplementsActionListener创建事件监视器创建事件监视器button.addActionListener(监视器监视器);实现接口中的方法实现接口中的方法publicvoidactionPerformed(ActinEvente)Java事件处理机制(续)适配器类适配器类适配器类不需要实现接口中所有适配器类不需要实现接口中所有方法,只需要实现部分方法即可,方法,只需要实现部分方法即可,它会将不需要实现的方法自动以它会将不需要实现的方法自动以空实现的方式实现。在空实现的方式实现。在Java类库类库中,中,Swing事件监视器接口有事件监视器接口有9个个适配器类适配器类。适配器类适配器类说明说明ComponentAdapter组件适配器组件适配器ContainerAdapter容器适配类容器适配类FocusAdapter焦点适配器焦点适配器KeyAdapter键盘适配器键盘适配器MouseAdapter鼠标适配器鼠标适配器MouseInputAdapter接收鼠标事件和接收鼠标事件和鼠标移动事鼠标移动事件的适配器件的适配器MouseMotionAdapter鼠标移动适配器鼠标移动适配器WindowAdapter窗口适配器窗口适配器HierarchyBoundsAdapter接收祖先的移动接收祖先的移动和大小重调和大小重调事件的抽象事件的抽象适配器适配器Java事件处理机制(续)常用事件监视器常用事件监视器接口名称:接口名称:ActionListener、ItemListener、TextListener、AdjustmentListener、MouseMotionListener、MouseListener、KeyListener、FocusListener、ComponentListener、WindowListener、ContainerListenerSwing常用组件-标签组件标签(标签(JLabel)用来显示提示信息。标)用来显示提示信息。标签可以显示文本和图标。签可以显示文本和图标。JLabel的常用属性的常用属性 :CENTER某区域的中心位置某区域的中心位置TOP用于指定框顶部位置的框方向常用于指定框顶部位置的框方向常量量LEFT用于指定框左侧位置的框方向常用于指定框左侧位置的框方向常量量BOTTOM用于指定框底部位置的框方用于指定框底部位置的框方向常量向常量RIGHT用于指定框右侧位置的框方向用于指定框右侧位置的框方向常量常量Swing常用组件-标签组件JLabel的常用方法的常用方法 :JLabel()创建无图像并且其标题为空字创建无图像并且其标题为空字符串的符串的JLabelJLabel(Iconimage)创建具有指定图像创建具有指定图像的的JLabel实例实例JLabel(Iconimage,intHalignment)创创建具有指定图像建具有指定图像image和水平对齐方式和水平对齐方式的的JLabel实例实例JLabel(Stringtext)创建具有指定文本的创建具有指定文本的JLabel实例实例JLabel(Stringtext,Iconicon,intHalignment)创建具有指定文本、图像和创建具有指定文本、图像和水平对齐方式的水平对齐方式的JLabel实例实例JLabel(Stringtext,intHalignment)创创建具有指定文本和水平对齐方式的建具有指定文本和水平对齐方式的JLabel实例实例setText(Strings)定义此组件将要显示的定义此组件将要显示的单行文本单行文本getTextl()返回该标签所显示的文本字符返回该标签所显示的文本字符串串Swing常用组件-标签组件setVerticalAlignment(intValignment)设置标签内容垂直方向的对齐方式,默设置标签内容垂直方向的对齐方式,默认值为认值为CENTER。getHorizontalAlignment()返回标签内返回标签内容水平方向的对齐方式。返回值为容水平方向的对齐方式。返回值为LEFT、CENTER、RIGHT、LEADING或或 TRAILINGsetHorizontalAlignment(intHalignment)设置标签内容水平方向的对设置标签内容水平方向的对齐方式。齐方式。getVerticalTextPosition()返回返回标签的文本相对其图像的垂直对齐方式,标签的文本相对其图像的垂直对齐方式,返回值为返回值为TOP、CENTER或或 BOTTOM其中参数其中参数Valignment选项为:选项为:TOP、CENTER或或 BOTTOM;参数;参数Halignment选项为:选项为:LEFT、CENTER(只显示图像的标签的默认值)、(只显示图像的标签的默认值)、RIGHT、LEADING(只显示文本的标签(只显示文本的标签的默认值)或的默认值)或 TRAILING。Swing常用组件-按钮组件按钮(按钮(JButton)是使用最为普遍的用户)是使用最为普遍的用户界面组件。按钮通常带有某种边框,且界面组件。按钮通常带有某种边框,且可以被鼠标或快捷键激活,能够完成某可以被鼠标或快捷键激活,能够完成某种功能。种功能。JButton的常用属性从的常用属性从javax.swing.SwingConstants继承而来,继承而来,与与JLabel相同相同JButton的常用方法的常用方法 :JButton()建立一个按钮建立一个按钮JButton(Iconicon)建立一个有图像的按建立一个有图像的按钮钮JButton(Stringicon)建立一个有文字的建立一个有文字的按钮按钮JButton(Stringtext,Iconicon)建立一建立一个有图像与文字的按钮个有图像与文字的按钮addActionListener(ActionListenerl)将一个将一个ActionListener添加到按钮中添加到按钮中getActionCommand()返回此按钮的动返回此按钮的动作命令作命令Swing常用组件-按钮组件getMnemonic()返回当前模型中的键盘返回当前模型中的键盘助记符助记符getText()返回按钮的文本返回按钮的文本setActionCommand(StringactionCommand)设置此按钮的动作命设置此按钮的动作命令,令,actionCommand为按钮的动作命令为按钮的动作命令setEnabled(booleanb)启用(或禁用)启用(或禁用)按钮,按钮,b为为true表示启用按钮,否则为禁表示启用按钮,否则为禁用用setHorizontalAlignment(intHalignment)设置图标和文本的水平对齐设置图标和文本的水平对齐方式方式setHorizontalTextPosition(inttextPosition)设置文本相对于图标的横设置文本相对于图标的横向位置向位置setText(Stringtext)设置按钮的文本设置按钮的文本setVerticalAlignment(intValignment)设置图标和文本的垂直对齐方式设置图标和文本的垂直对齐方式Swing常用组件-按钮组件按钮上事件、事件监视器和接口:按钮上事件、事件监视器和接口:按钮可发生按钮可发生ActionEvent事件事件事件监视器接口为事件监视器接口为ActionListener接口接口该接口中的抽象方法为:该接口中的抽象方法为:publicvoidactionPerformed(ActionEvente)Swing常用组件-文本型组件文本框组件(文本框组件(JTextField)文本框组件用来接受用户输入的单行文文本框组件用来接受用户输入的单行文本信息。本信息。JTextField的常用属性的常用属性 :notifyAction发送通知(已接收字段内容)发送通知(已接收字段内容)的动作名称。通常它必须绑定到回车操的动作名称。通常它必须绑定到回车操作作CENTER某区域的中心位置某区域的中心位置TOP用于指定框顶部位置的框方向常用于指定框顶部位置的框方向常量量LEFT用于指定框左侧位置的框方向常用于指定框左侧位置的框方向常量量BOTTOM用于指定框底部位置的框方用于指定框底部位置的框方向常量向常量RIGHT用于指定框右侧位置的框方向用于指定框右侧位置的框方向常量常量Swing常用组件-文本型组件JTextField的常用方法的常用方法 :JTextField()构造一个新的文本框构造一个新的文本框JTextField(intcolumns)构造一个具有指构造一个具有指定列数的新的空定列数的新的空TextFieldJTextField(Strings)构造一个用构造一个用指定文本初始化的新指定文本初始化的新TextFieldJTextField(Strings,intcolumns)构造一构造一个用指定文本和列初始化的新个用指定文本和列初始化的新TextFieldsetText(Strings)设置文本框中的文本为设置文本框中的文本为参数参数s指定的文本指定的文本getText()获取文本框中的文本获取文本框中的文本setEditable(booleanb)设置文本框的可设置文本框的可编辑性编辑性addActionListener(ActionListenerl)添添加指定的操作侦听器加指定的操作侦听器l以从此文本字段接收操以从此文本字段接收操作事件作事件Swing常用组件-文本型组件removeActionListener(ActionListenerl)移除指定的操作侦听器,以便不再移除指定的操作侦听器,以便不再从此文本字段接收操作事件从此文本字段接收操作事件getColumns()返回此返回此TextField中的中的列数列数setColumns(intcolumns)设置此设置此TextField中的列数,然后验证布局中的列数,然后验证布局setFont(Fontf)设置当前字体设置当前字体f。这将。这将移除缓存的行高和列宽,以便新的字体移除缓存的行高和列宽,以便新的字体能够反映出来,设置字体后将调用能够反映出来,设置字体后将调用 revalidate文本框上回车时发生的事件、接口及需文本框上回车时发生的事件、接口及需要实现的方法和要实现的方法和JButton相同。相同。Swing常用组件-文本型组件密码框组件(密码框组件(JPasswordField)密码框组件是一个轻量级组件,允许编辑一个单行文本,但不显示原始字符,密码框组件是一个轻量级组件,允许编辑一个单行文本,但不显示原始字符,默认的回显字符为默认的回显字符为“*”“*”。JPasswordField的常用属性与的常用属性与JTextField相同相同 JPasswordField的常用方法的常用方法 :JPasswordField()构造一个新构造一个新JPasswordField,使其具有默认文档、为,使其具有默认文档、为null的开始文本字符串和为的开始文本字符串和为 0的列宽度的列宽度JPasswordField(Stringtext)构造一个利用指定文本初始化的新构造一个利用指定文本初始化的新JPasswordField。将文档模型设置为默认值,列数为。将文档模型设置为默认值,列数为0JPasswordField(intcolumns)构造一个具有指定列数的新的空构造一个具有指定列数的新的空JPasswordField。创建一个默认模型,并将其初始字符串设置为。创建一个默认模型,并将其初始字符串设置为nullJPasswordField(Stringtext,intcolumns)构造一个利用指定文本和列构造一个利用指定文本和列初始化的新初始化的新JPasswordField。将文档模型设置为默认值。将文档模型设置为默认值getEchoChar()返回要用于回显的字符。默认值为返回要用于回显的字符。默认值为“*”“*”。默认值根据当。默认值根据当前运行的外观可以有所不同。如果未设置,则返回前运行的外观可以有所不同。如果未设置,则返回0Swing常用组件-文本型组件getPassword()返回此返回此TextComponent中所包含的文本。如果中所包含的文本。如果基础文档为基础文档为null,则将给出,则将给出NullPointerException。为了取得较高。为了取得较高的安全性,建议将每个字符设置为的安全性,建议将每个字符设置为0以便以便在使用后清除返回的字符数组在使用后清除返回的字符数组setEchoChar(charc)建议设置此建议设置此JPasswordField的回显字符。将值设置的回显字符。将值设置为为0指示希望按照键入查看文本,类似于指示希望按照键入查看文本,类似于标准标准JTextField的行为。的行为。c是要显示的回是要显示的回显字符显字符其中表中参数其中表中参数text是要显示的文本,如果是要显示的文本,如果没有文本,则为没有文本,则为null;参数;参数columns代代表列数,值大于等于表列数,值大于等于0。密码框组件回车时发生的事件、接口及密码框组件回车时发生的事件、接口及需要实现的方法和需要实现的方法和JTextField相同。相同。Swing常用组件-文本型组件文本区组件(文本区组件(JTextArea)文本区组件是一个显示纯文本的多行区文本区组件是一个显示纯文本的多行区域。域。JTextArea的常用属性的常用属性 :BOTTOM_ALIGNMENT指定组件底指定组件底部对齐方式部对齐方式LEFT_ALIGNMENT指定指定组件左对齐方式组件左对齐方式RIGHT_ALIGNMENT指定组件右对齐方式指定组件右对齐方式TOP_ALIGNMENT指定组件顶部对齐方式指定组件顶部对齐方式CENTER_ALIGNMENT指定组件居中指定组件居中对齐方式对齐方式Swing常用组件-文本型组件JTextArea的常用方法的常用方法 :JTextArea()构造新的文本区。设置默认构造新的文本区。设置默认的模型,初始字符串为的模型,初始字符串为 null,行,行/列设置为列设置为0JTextArea(Stringtext)构造显示指定文构造显示指定文本的新的文本区。创建默认模型,行本的新的文本区。创建默认模型,行/列设列设置为置为0JTextArea(introws,intcolumns)构造构造具有指定行数和列数的新的空文本区。创具有指定行数和列数的新的空文本区。创建默认模型,初始字符串为建默认模型,初始字符串为nullJTextArea(Stringtext,introws,intcolumns)构造具有指定文本、行数和列数的构造具有指定文本、行数和列数的新的文本区。创建默认模型新的文本区。创建默认模型JTextArea(Documentdoc,Stringtext,introws,intcolumns)构造具有指定行构造具有指定行数和列数以及给定模型数和列数以及给定模型doc的新的的新的JTextArea。所有构造方法均调用此构造。所有构造方法均调用此构造方法方法setText(Stringtext)将文本区中的文本将文本区中的文本设置为参数指定的文本设置为参数指定的文本getText()获取文本区中的文本获取文本区中的文本insert(Strings,intx)在指定位置在指定位置x处,处,插入指定文本插入指定文本sSwing常用组件-文本型组件replaceRange(Stringtext,intstart,intend)用所给的新文本用所给的新文本text替换从指定替换从指定位置位置start开始到指定位置开始到指定位置end结束的文结束的文本本append(Stringtext)将给定文本将给定文本text追加到文档结尾追加到文档结尾getColumns()返回文本区中的列数大返回文本区中的列数大于等于于等于0getColumnWidth()获取列的宽度,列获取列的宽度,列的宽度大于等于的宽度大于等于1getLineCount()确定文本区中所包含确定文本区中所包含的行数,其值大于的行数,其值大于0getLineWrap()获取文本区的换行策略。获取文本区的换行策略。如果设置为如果设置为true,则当行的长度大于所,则当行的长度大于所分配的宽度时,将换行。如果设置为分配的宽度时,将换行。如果设置为false,则始终不换行,则始终不换行getRows()返回文本区中的行数大于返回文本区中的行数大于0setColumns(intcolumns)设置此文设置此文本区中的列数。设置新值之后执行本区中的列数。设置新值之后执行invalidate()Swing常用组件-文本型组件setFont(Fontf)设置当前字体设置当前字体f。这将。这将移除缓存的行高和列宽,以便新的字体移除缓存的行高和列宽,以便新的字体能够反映出来,并且调用能够反映出来,并且调用revalidate()setLineWrap(booleanwrap)设置文设置文本区的换行策略。如果本区的换行策略。如果wrap设置为设置为true,则当行的长度大于所分配的宽度时,则当行的长度大于所分配的宽度时,将换行。如果设置为将换行。如果设置为false,则始终不换,则始终不换行、行、setRows(introws)设置此文本区的行设置此文本区的行数。设置新值之后调用数。设置新值之后调用invalidate()setWrapStyleWord(booleanword)设置换行方式(如果文本区要换行)。设置换行方式(如果文本区要换行)。如果如果word设置为设置为 true,则当行的长度大,则当行的长度大于所分配的宽度时,将在单词边界(空于所分配的宽度时,将在单词边界(空白)处换行。如果设置为白)处换行。如果设置为false,则将在,则将在字符边界处换行。此属性默认为字符边界处换行。此属性默认为false其中表中的参数其中表中的参数text是要显示的文本,可是要显示的文本,可以为以为null;参数;参数rows和和columns分别代分别代表行数和列数,其值大于等于表行数和列数,其值大于等于0。 Swing常用组件-文本型组件文本区事件、事件监视器和接口:文本区事件、事件监视器和接口:文本区可发生文本区可发生DocumentEvent事件事件事件监视器接口为事件监视器接口为DocumentListener接接口口该接口中的抽象方法为:该接口中的抽象方法为:voidchangedUpdate(DocumentEvente)给出属性或属性集发生了更改的通知给出属性或属性集发生了更改的通知voidinsertUpdate(DocumentEvente)给出给出对文档执行了插入操作的通知对文档执行了插入操作的通知voidremoveUpdate(DocumentEvente)给给出移除了一部分文档的通知出移除了一部分文档的通知 Swing常用组件-选择型组件单选按钮组件(单选按钮组件(JRadioButton)单选按钮组件实现用户的单一选择,用单选按钮组件实现用户的单一选择,用户可以很方便地查看单选按钮的状态。户可以很方便地查看单选按钮的状态。JRadioButton类可以单独使用,也可以类可以单独使用,也可以与与ButtonGroup类联合使用,当单独使类联合使用,当单独使用时,可以被选定和取消选定,当与用时,可以被选定和取消选定,当与ButtonGroup类联合使用时,则组成了类联合使用时,则组成了一个单选按钮组,此时用户只能选定按一个单选按钮组,此时用户只能选定按钮组中的一个单选按钮,取消选定的操钮组中的一个单选按钮,取消选定的操作将由作将由ButtonGroup类自动完成。类自动完成。JRadioButton的常用属性与的常用属性与JTextArea相同相同 Swing常用组件-选择型组件JRadioButton的常用方法的常用方法 :JRadioButton()建立一个新的建立一个新的JRadioButtonJRadioButton(Iconicon)建立一个有图像但没有文字的建立一个有图像但没有文字的JRadioButtonJRadioButton(Iconicon,booleanselected)建立一个有图建立一个有图像但没有文字的像但没有文字的JRadioButton,且设置,且设置其初始状态其初始状态(有无被选取有无被选取)JRadioButton(Stringtext)建立一个建立一个有文字的有文字的JRadioButtonJRadioButton(Stringtext,booleanselected)建立一个有文字的建立一个有文字的JRadioButton,且设置其初始状态(有,且设置其初始状态(有无被选取)无被选取)JRadioButton(Stringtext,Iconicon)建立一个有文字且有图像的建立一个有文字且有图像的JRadioButton,初始状态为无被选取,初始状态为无被选取JRadioButton(Stringtext,Iconicon,booleanselected)建立一个有文建立一个有文字且有图像的字且有图像的JRadioButton,且设置其,且设置其初始状态初始状态(有无被选取有无被选取)Swing常用组件-选择型组件getText()获取单选按钮的名称获取单选按钮的名称setText(Strings)将单选按钮的名称将单选按钮的名称设置为指定的字符串设置为指定的字符串ssetSelected(booleanb)设置单选按设置单选按钮的状态钮的状态isSelected()返回按钮的状态。返回按钮的状态。如果选定了切换按钮,则返回如果选定了切换按钮,则返回true,否,否则返回则返回falsesetHideActionText(booleanhideActionText)设置设置hideActionText属性,该属性,该属性确定按钮是否显示属性确定按钮是否显示Action的文本。的文本。只有在按钮上已安装了只有在按钮上已安装了Action时,此方时,此方法才有用。参数法才有用。参数hideActionText是指如是指如果按钮的果按钮的text属性不应该反映属性不应该反映Action的的文本,则该参数为文本,则该参数为true;默认情况下为;默认情况下为falseSwing常用组件-选择型组件单选按钮上发生的事件:单选按钮上发生的事件:单选按钮可发生单选按钮可发生ItemEvent事件事件事件监视器接口为事件监视器接口为ItemListener接口接口该接口中的抽象方法为:该接口中的抽象方法为:publicvoiditemStateChanged(ItemEvente)其中,其中,ItemEvent类提供以下两种方法:类提供以下两种方法:ItemSelectablegetItemSelectable()/返回引发选择变化的事件源返回引发选择变化的事件源intgetStateChange()/返回改变的状态返回改变的状态Swing常用组件-选择型组件ButtonGroup类用来创建一个按钮组,类用来创建一个按钮组,按钮组的作用是负责维护该组按钮的按钮组的作用是负责维护该组按钮的“开启开启”状态,在按钮组中只能有一个按状态,在按钮组中只能有一个按钮处于钮处于“开启开启”状态。状态。ButtonGroup提供的常用方法提供的常用方法 :add(AbstractButtonb)添加按钮到按添加按钮到按钮组中钮组中remove(AbstractButtonb)从按钮组从按钮组中移除按钮中移除按钮getButtonCount()返回按钮组中包含返回按钮组中包含按钮的个数,返回值为按钮的个数,返回值为int型型getElements()返回一个返回一个Enumeration类类型的对象,通过该对象可以遍历按钮组型的对象,通过该对象可以遍历按钮组中包含的所有按钮对象中包含的所有按钮对象Swing常用组件-选择型组件选择框组件(选择框组件(JCheckBox)选择框(也被称为复选框)提供两种状态,选择框(也被称为复选框)提供两种状态,一种是选中,另一种是未选中,实现用户一种是选中,另一种是未选中,实现用户的多种选择。的多种选择。JCheckBox的常用方法的常用方法 :JCheckBox()创建一个没有文本、没有创建一个没有文本、没有图标并且最初未被选定的复选框图标并且最初未被选定的复选框JCheckBox(Iconicon)创建有一个图标、创建有一个图标、最初未被选定的复选框最初未被选定的复选框JCheckBox(Stringtext)创建一个带文创建一个带文本的、最初未被选定的复选框本的、最初未被选定的复选框JCheckBox(Actiona)创建一个复选框,创建一个复选框,其属性从所提供的其属性从所提供的Action获取获取JCheckBox(Stringtext,booleanselected)创建一个带文本的复选框,并指定其创建一个带文本的复选框,并指定其最初是否处于选定状态最初是否处于选定状态JCheckBox(Stringtext,Iconicon)创创建带有指定文本和图标的、最初未选定的建带有指定文本和图标的、最初未选定的复选框复选框JCheckBox(Stringtext,Iconicon,booleanselected)创建一个带文本和图标的创建一个带文本和图标的复选框,并指定其最初是否处于选定状态复选框,并指定其最初是否处于选定状态Swing常用组件-选择型组件addItemListener(ItemListenerl)向选择框增加监视向选择框增加监视ItemEvent事件事件的监视器的监视器lremoveItemListener(ItemListenerl)移去选择框上的移去选择框上的ItemEvent事件事件的监视器的监视器lgetText()获取选择框的名称获取选择框的名称setText(Strings)将选择框的名称设置为指定的字符串将选择框的名称设置为指定的字符串ssetSelected(booleanb)设置选择框的状态设置选择框的状态isBorderPaintedFlat()获取获取borderPaintedFlat属性的值属性的值setBorderPaintedFlat(booleanb)设置设置borderPaintedFlat属性,该属性,该属性为外观提供了关于复选框边框外观的提示。在属性为外观提供了关于复选框边框外观的提示。在JCheckBox实例用作实例用作组件(如组件(如JTable或或JTree)中的渲染器时,该属性通常被设置为)中的渲染器时,该属性通常被设置为true。borderPaintedFlat属性的默认值为属性的默认值为false。此方法触发一个属性更改事。此方法触发一个属性更改事件。一些外观也许不实现平面边框;它们将忽略此属性。参数件。一些外观也许不实现平面边框;它们将忽略此属性。参数b为为true则则请求将边框绘制为平面的;为请求将边框绘制为平面的;为false则请求为普通边框则请求为普通边框Swing常用组件-选择型组件其中表中参数其中表中参数icon是要显示的是要显示的Icon图像;图像;参数参数selected指示最初选择状态的指示最初选择状态的boolean值,如果该参数为值,如果该参数为true,则复选,则复选框被选定;参数框被选定;参数text是复选框的文本。是复选框的文本。选择框上发生的事件、接口及需要实现选择框上发生的事件、接口及需要实现的方法和的方法和JRadioButton相同相同 Swing常用组件-选择型组件下拉列表框组件(下拉列表框组件(JComboBox)下拉列表框组件是将按钮或可编辑字段下拉列表框组件是将按钮或可编辑字段与下拉列表组合的组件。用户可以从下与下拉列表组合的组件。用户可以从下拉列表中选择值,下拉列表在用户请求拉列表中选择值,下拉列表在用户请求时显示。如果使组合框处于可编辑状态,时显示。如果使组合框处于可编辑状态,则组合框将包括用户可在其中键入值的则组合框将包括用户可在其中键入值的可编辑字段。可编辑字段。JComboBox的常用属性的常用属性 :dataModel数据模型数据模型Renderer渲染器渲染器Editor编辑器编辑器maximumRowCount不使用滚动条可不使用滚动条可以显示的最大项数以显示的最大项数isEditable可编辑可编辑Swing常用组件-选择型组件JComboBox的常用方法的常用方法 :JComboBox()创建具有默认数据模型的创建具有默认数据模型的JComboBox。默认的数据模。默认的数据模型为空对象列表。使用型为空对象列表。使用addItem添加项。默认情况下,选择数据模型中的添加项。默认情况下,选择数据模型中的第一项第一项JComboBox(ComboBoxModelaModel)创建一个创建一个JComboBox,其,其项取自现有的项取自现有的ComboBoxModel。由于提供了。由于提供了ComboBoxModel,使用,使用此构造方法创建的组合框不创建默认组合框模型,这可能影响插入、移除此构造方法创建的组合框不创建默认组合框模型,这可能影响插入、移除和添加方法的行为方式。参数和添加方法的行为方式。参数aModel提供显示的项列表的提供显示的项列表的ComboBoxModelJComboBox(Objectitems)创建包含指定数组中的元素的创建包含指定数组中的元素的JComboBox。默认情况下,选择数组中的第一项(因而也选择了该项的。默认情况下,选择数组中的第一项(因而也选择了该项的数据模型)。参数数据模型)。参数items是要插入到组合框的对象数组是要插入到组合框的对象数组removeActionListener(ActionListenerl)移除移除ActionListenerremoveAllItems()从选项列表中移除所有项从选项列表中移除所有项removeItem(ObjectanObject)从选项列表中移除项从选项列表中移除项removeItemAt(intanIndex)移除移除anIndex处的项处的项Swing常用组件-选择型组件addItem(Objectitem)为选项列表添加项为选项列表添加项insertItemAt(Objectitem,intindex)在选在选项列表中的给定索引处插入项项列表中的给定索引处插入项setSelectedItem(ObjectanObject)将组合将组合框显示区域中所选项设置为参数中的对象框显示区域中所选项设置为参数中的对象setMaximumRowCount(intcount)设置设置JComboBox显示的最大行数显示的最大行数setEditable(booleanaFlag)确定确定JComboBox字段是否可编辑字段是否可编辑setSelectedIndex(intanIndex)选择索引选择索引anIndex处的项处的项setModel(ComboBoxModelaModel)设置设置JComboBox用于获取项列表的数据模型用于获取项列表的数据模型下拉列表框上可以发生下拉列表框上可以发生ActionEvent、ItemEvent等多个事件,但其主要使用的事等多个事件,但其主要使用的事件是件是ActionEvent,其接口及实现方法和,其接口及实现方法和JRadioButton相同相同 Swing常用组件-选择型组件列表框组件(列表框组件(JList)列表框组件实现一个列表框,列表框与选择框的主要区别就是列表框可列表框组件实现一个列表框,列表框与选择框的主要区别就是列表框可以多选。以多选。JList的常用属性的常用属性 :BOTTOM_ALIGNMENT指定组件底部对齐方式指定组件底部对齐方式LEFT_ALIGNMENT指定组件左对齐方式指定组件左对齐方式RIGHT_ALIGNMENT指定组件右对齐方式指定组件右对齐方式TOP_ALIGNMENT指定组件顶部对齐方式指定组件顶部对齐方式CENTER_ALIGNMENT指定组件居中对齐方式指定组件居中对齐方式HORIZONTAL_WRAP指示指示“报纸样式报纸样式”布局,单元按先水平后垂直排布局,单元按先水平后垂直排列列VERTICAL指示单个列中单元的垂直布局;默认布局指示单个列中单元的垂直布局;默认布局VERTICAL_WRAP指示指示“报纸样式报纸样式”布局,单元按先垂直后水平排列布局,单元按先垂直后水平排列Swing常用组件-选择型组件JList的常用方法的常用方法 :JList()构造一个使用空模型的构造一个使用空模型的JListJList(ListModeldataModel)构造一个构造一个JList,使其使用指定的非,使其使用指定的非null模型显示模型显示元素元素setSelectedIndex(intindex)选中指定选中指定索引的一个选项索引的一个选项setSelectedIndices(intindices)选选中指定索引的一组选项中指定索引的一组选项getSelectedIndices()以以int形式获得形式获得被选中的所有选项的索引值被选中的所有选项的索引值getSelectedValues()以以Object形式形式获得被选中的所有选项的内容获得被选中的所有选项的内容clearSelection()取消所有被选中的项取消所有被选中的项isSelectionEmpty()查看是否有被选中查看是否有被选中的项,如果有则返回的项,如果有则返回trueisSelectedIndex(intindex)查看指定查看指定项是否已经被选中项是否已经被选中Swing常用组件-选择型组件ensureIndexIsVisible(intindex)使指使指定项在选择窗口中可见定项在选择窗口中可见setVisibleRowCount(intvisibleRowCount)设置在选择窗口中设置在选择窗口中最多可见选项的个数最多可见选项的个数setSelectionMode(intselectionMode)设置列表框的选择模式,即单选还是多设置列表框的选择模式,即单选还是多选选setModel(ListModelmodel)设置表示设置表示列表内容或列表列表内容或列表“值值”的模型,通知属的模型,通知属性更改侦听器,然后清除列表选择性更改侦听器,然后清除列表选择列表框上发生的事件:列表框上发生的事件:单选按钮可发生单选按钮可发生ListSelectionEvent事事件件事件监视器接口为事件监视器接口为ListSelectionListener接口接口该接口中的抽象方法为:该接口中的抽象方法为:publicvoidvalueChanged(ListSelectionEventevent)菜单菜单分为两类,一类是固定的,一类是菜单分为两类,一类是固定的,一类是弹出式菜单弹出式菜单 菜单-固定的菜单固定的菜单是图形界面中最常用的一种固定的菜单是图形界面中最常用的一种菜单形式。固定菜单一般包括菜单条、菜单形式。固定菜单一般包括菜单条、菜单组和菜单项。创建一个固定菜单要菜单组和菜单项。创建一个固定菜单要分成三步:分成三步:创建菜单条创建菜单条创建菜单,将菜单加入菜单条创建菜单,将菜单加入菜单条创建菜单项实现用户需要的功能,将菜创建菜单项实现用户需要的功能,将菜单项加入菜单单项加入菜单 菜单条(菜单条(JMenubar)JMenubar类负责创建菜单条,菜单条将类负责创建菜单条,菜单条将被添加到窗口的顶端。被添加到窗口的顶端。JMenubar菜单条菜单条不具备不具备Windows特性,它也不具备顶层特性,它也不具备顶层容器类的特性,即不能独立显示出来,容器类的特性,即不能独立显示出来,需要依赖顶层容器。需要依赖顶层容器。菜单-固定的菜单JMenubar的常用属性:的常用属性:listenerList事件侦听器列表事件侦听器列表TOOL_TIP_TEXT_KEY光标位于组件光标位于组件上方时显示的注释上方时显示的注释WHEN_FOCUSED用于用于registerKeyboardAction的常量,意味的常量,意味着在组件获得焦点时应该调用命令着在组件获得焦点时应该调用命令WHEN_IN_FOCUSED_WINDOW用用于于registerKeyboardAction的常量,意的常量,意味着当接收组件处于获得焦点的窗口内味着当接收组件处于获得焦点的窗口内或者其本身就是获得焦点的组件时,应或者其本身就是获得焦点的组件时,应该调用命令该调用命令菜单-固定的菜单JMenubar的常用方法的常用方法 :JMenubar()创建新的菜单栏创建新的菜单栏add(JMenuc)将指定的菜单追加到菜将指定的菜单追加到菜单栏的末尾单栏的末尾getMenu(intindex)返回菜单栏中指返回菜单栏中指定位置的菜单。参数定位置的菜单。参数index是给出菜单栏是给出菜单栏中位置的整数,第一个位置是中位置的整数,第一个位置是0getMenuCount()返回菜单栏上的菜单返回菜单栏上的菜单数数isSelected()如果当前已选择了菜单栏如果当前已选择了菜单栏的组件,则返回的组件,则返回truesetSelected(Componentsel)设置当设置当前选择的组件,更改选择模型前选择的组件,更改选择模型JFrame类提供类提供setJMenuBar(JMenuBarmenubar)方方法可以将菜单条添加到窗口顶端。法可以将菜单条添加到窗口顶端。菜单-固定的菜单菜单(菜单(JMenu)JMenu类负责创建菜单,菜单将被放在菜单条里。类负责创建菜单,菜单将被放在菜单条里。JMenu的常用方法的常用方法 :JMenu()构造没有文本的新构造没有文本的新 JmenuJMenu(Strings)构造一个新构造一个新 JMenu,用提供的字符串作为其文本,用提供的字符串作为其文本add(JMenuItemmenuItem)将某个菜单项追加到此菜单的末尾将某个菜单项追加到此菜单的末尾add(Strings)创建具有指定文本的菜单项,并将其追加到此菜单的末创建具有指定文本的菜单项,并将其追加到此菜单的末尾尾getItem(intpos)返回指定位置的返回指定位置的JMenuItemgetItemCount()返回菜单上的项数,包括分隔符返回菜单上的项数,包括分隔符insert(JMenuItemmi,intpos)在给定位置插入指定的在给定位置插入指定的JMenuiteminsert(Strings,intpos)在给定的位置插入一个具有指定文本的新菜在给定的位置插入一个具有指定文本的新菜单项单项菜单-固定的菜单remove(Componentc)从此菜单移除组件从此菜单移除组件cremove(intpos)从此菜单移除指定索引处的菜单项从此菜单移除指定索引处的菜单项remove(JMenuItemitem)从此菜单移除指定的菜单项从此菜单移除指定的菜单项removeAll()从此菜单移除所有菜单项从此菜单移除所有菜单项菜单项(菜单项(JMenuItem)JMenuItem类负责创建菜单项,菜单项将被放在菜单里。类负责创建菜单项,菜单项将被放在菜单里。JMenuItem的常用方法的常用方法 :JMenuItem()创建不带有设置文本或图标的创建不带有设置文本或图标的JMenuItemJMenuItem(Stringtext)创建带有指定文本的创建带有指定文本的JmenuItemsetEnabled(booleanb)启用或禁用菜单项启用或禁用菜单项getLabel()返回菜单选项的名字返回菜单选项的名字addActionListener(ActionListenerl)向菜单项增加监视器,从菜单项向菜单项增加监视器,从菜单项接受行动事件(单击某个菜单项)接受行动事件(单击某个菜单项)菜单项上可以发生菜单项上可以发生ActionEvent,其接口及实现方法和,其接口及实现方法和JButton相同。相同。菜单-固定的菜单例如,在例如,在JFrame顶端创建顶端创建“文件文件”菜单,菜单,在在“文件文件”菜单中创建菜单中创建“添加添加”、“删删除除”和和“退出退出”子菜单。程序主要代码子菜单。程序主要代码如下:如下:JFramejf=newJFrame();JMenuBarmenubar=newJMenuBar();jf.setJMenuBar(menubar);JMenumenuFile=newJMenu(文件文件);menubar.add(menuFile);JMenuItemadd=newJMenuItem(添添加加);JMenuItemdel=newJMenuItem(删删除除);JMenuItemexit=newJMenuItem(退退出出);menuFile.add(add);menuFile.add(del);menuFile.add(exit);jf.setVisible(true);菜单-弹出式菜单弹出式菜单的建立与普通菜单类似,但弹出式菜单的建立与普通菜单类似,但可以不需要加标题。创建弹出式菜单的可以不需要加标题。创建弹出式菜单的步骤分成三步:步骤分成三步:创建一个空的弹出式菜单创建一个空的弹出式菜单将菜单项添加到弹出式菜单中将菜单项添加到弹出式菜单中在容器中添加鼠标右键事件的处理代码在容器中添加鼠标右键事件的处理代码 JPopupMenu的常用方法的常用方法 :JPopupMenu()构造一个不带构造一个不带“调用调用者者”的的JPopupMenuJPopupMenu(Stringlabel)构造一个构造一个具有指定标题的具有指定标题的JPopupMenu。参数。参数label可以被可以被UI用作弹出菜单的标题显示用作弹出菜单的标题显示的字符串的字符串add(JMenuItemmenuItem)将指定菜将指定菜单项添加到此菜单的末尾单项添加到此菜单的末尾菜单-弹出式菜单add(Strings)创建具有指定文本的菜创建具有指定文本的菜单项,并将其添加到此菜单的末尾单项,并将其添加到此菜单的末尾addSeparator()将新分隔符添加到菜将新分隔符添加到菜单的末尾单的末尾getLabel()返回弹出菜单的标签返回弹出菜单的标签setPopupSize(intwidth,intheight)将弹出窗口的大小设置为指定的宽度和将弹出窗口的大小设置为指定的宽度和高度高度addMenuKeyListener(MenuKeyListenerl)将将l添加到弹出菜单添加到弹出菜单addPopupMenuListener(PopupMenuListenerl)添加添加PopupMenu监视器监视器show(Componentinvoker,intx,inty)在组件调用者的坐标空间中的位置在组件调用者的坐标空间中的位置X、Y显示弹出菜单。参数显示弹出菜单。参数invoker指弹出菜单指弹出菜单在其空间中显示的组件;参数在其空间中显示的组件;参数x用于显示用于显示弹出菜单的调用者的坐标空间中的弹出菜单的调用者的坐标空间中的X坐标;坐标;参数参数y用于显示弹出菜单的调用者的坐标用于显示弹出菜单的调用者的坐标空间中的空间中的Y坐标坐标菜单-弹出式菜单例如,创建一个弹出式菜单,包括例如,创建一个弹出式菜单,包括“添加添加”、“删除删除”和和“退出退出”菜单。程菜单。程序主要代码如下:序主要代码如下:JPopupMenupopup=newJPopupMenu();JMenuItemadd=newJMenuItem(添加添加);JMenuItemdel=newJMenuItem(删除删除);JMenuItemexit=newJMenuItem(退出退出);popup.add(add);popup.add(del);popup.add(exit);addMouseListener(newMouseAdapter()/添加鼠标右键事件的处理添加鼠标右键事件的处理代码代码publicvoidmouseReleased(MouseEventevent)if(event.isPopupTrigger()popup.show(event.getComponent(),event.getX(),event.getY(););JAppletJApplet类继承了类继承了Applet类,而类,而Applet类是类是Panel类的子类。通过继承类的子类。通过继承javax.swing.JApplet来实现来实现Applet编程。编程。在在JavaApplet中,可以实现图形绘制、字体和颜色控制、动画和声音的中,可以实现图形绘制、字体和颜色控制、动画和声音的插入、人机交互及网络交流等功能。插入、人机交互及网络交流等功能。Applet程序的特点程序的特点一个一个JavaApplet程序中必须有一个类是程序中必须有一个类是Applet类的子类,该子类是类的子类,该子类是JavaApplet程序的主类,并且主类必须修饰为程序的主类,并且主类必须修饰为public的。的。Applet程序是程序是一种不能单独运行但可嵌入在其他应用程序中的小程序。一种不能单独运行但可嵌入在其他应用程序中的小程序。Applet类提供类提供了了JavaApplet程序及其运行环境之间的标准接口。程序及其运行环境之间的标准接口。Applet生命周期生命周期JavaApplet应用程序的生命周期相对于应用程序的生命周期相对于Application而言较为复杂。在而言较为复杂。在JavaApplet的生命周期中,共有初始态、运行态、停止态和消亡态四种的生命周期中,共有初始态、运行态、停止态和消亡态四种状态。状态。JAppletApplet常用方法:常用方法: init()初始化处理初始化处理start()启动启动Applet时所要做的工作时所要做的工作paint(g)在在Applet的界面中绘制文字、的界面中绘制文字、图形等图形等update(g)实现实现Applet画面的刷新画面的刷新,默默认清除画面后调认清除画面后调paint(g)repaint()重新绘制,它将调用重新绘制,它将调用update(g)stop()停止停止Applet前所要做的工作前所要做的工作destroy()浏览器关闭,浏览器关闭,Applet退出前退出前所要做的工作所要做的工作getGraphics()为组件创建一个图形上为组件创建一个图形上下文下文JAppletApplet的图形绘制的图形绘制借助借助Applet的的“画笔画笔”(Graphics)对)对象可调用如表象可调用如表8.24所示的方法实现各类所示的方法实现各类图形的绘制。在图形的绘制。在paint方法执行时,方法执行时,Applet将自动将自己的将自动将自己的“画笔画笔”通过参通过参数传递给方法,在其它情形下,也可以数传递给方法,在其它情形下,也可以通过由父类通过由父类Component继承而来的继承而来的getGraphics()方法得到方法得到“画笔画笔”。 Graphics常用方法常用方法 :setColor(Colorc)设置当前颜色为指设置当前颜色为指定颜色定颜色cdrawString(Strings,intx,inty)绘绘制文字制文字drawLine(intx1,inty1,intx2,inty2)绘制直线绘制直线drawRect(intx,inty,intwidth,intheight)绘制矩形绘制矩形JAppletdrawOval(intx,inty,intwidth,intheight)绘制椭圆绘制椭圆drawPolygon(intxPoints,intyPoints,intnPoints)绘制多边形绘制多边形drawArc(intx,inty,intwidth,intheight,intstartAngle,intarcAngle)绘制圆弧绘制圆弧drawRoundRect(intx,inty,intwidth,intheight,intarcWidth,intarcHeight)绘制园角矩形绘制园角矩形fillOval(intx,inty,intwidth,intheight)绘制填充椭圆绘制填充椭圆fillRect(intx,inty,intwidth,intheight)绘制填充矩形绘制填充矩形fillRoundRect(intx,inty,intwidth,intheight,intarcWidth,intarcHeight)绘制填充园角矩形绘制填充园角矩形fillArc(intx,inty,intwidth,intheight,intstartAngle,intarcAngle)绘制填充绘制填充扇形扇形本章小结Java事件处理流程为组件发生动作后,事件处理流程为组件发生动作后,产生相应的事件,事件被传递给相应的产生相应的事件,事件被传递给相应的监视器(或适配器),监视器(或适配监视器(或适配器),监视器(或适配器)调用相应处理方法来处理事件。器)调用相应处理方法来处理事件。javax.swing.event包中提供了许多事包中提供了许多事件类和处理各种事件的接口。件类和处理各种事件的接口。Swing事事件监视器接口有件监视器接口有ComponentAdapter、ContainerAdapter、FocusAdapter、KeyAdapter、MouseAdapter、MouseInputAdapter、MouseMotionAdapter、WindowAdapter、HierarchyBoundsAdapter9个适配器类。个适配器类。 本章小结(续)常用组件常用组件标签(标签(JLabel)用来显示提示信息。标)用来显示提示信息。标签可以显示文本和图标。签可以显示文本和图标。按钮(按钮(JButton)是使用最为普遍的用户)是使用最为普遍的用户界面组件。按钮通常带有某种边框,且界面组件。按钮通常带有某种边框,且可以被鼠标或快捷键激活,能够完成某可以被鼠标或快捷键激活,能够完成某种功能。种功能。按钮可发生按钮可发生ActionEvent事件,事件监视事件,事件监视器接口为器接口为ActionListener接口,该接口接口,该接口中的抽象方法为:中的抽象方法为:publicvoidactionPerformed(ActionEvente)文本框组件(文本框组件(JTextField)用来接受用户)用来接受用户输入的单行文本信息。文本框上回车时输入的单行文本信息。文本框上回车时发生的事件、接口及需要实现的方法和发生的事件、接口及需要实现的方法和JButton相同。相同。 本章小结(续)单选按钮组件(单选按钮组件(JRadioButton)单选按钮组件实现用户的单一选择,用单选按钮组件实现用户的单一选择,用户可以很方便地查看单选按钮的状态。户可以很方便地查看单选按钮的状态。JRadioButton类可以单独使用,也可以类可以单独使用,也可以与与ButtonGroup类联合使用,当单独使类联合使用,当单独使用时,可以被选定和取消选定,当与用时,可以被选定和取消选定,当与ButtonGroup类联合使用时,则组成了类联合使用时,则组成了一个单选按钮组,此时用户只能选定按一个单选按钮组,此时用户只能选定按钮组中的一个单选按钮,取消选定的操钮组中的一个单选按钮,取消选定的操作将由作将由ButtonGroup类自动完成。类自动完成。单选按钮可发生单选按钮可发生ItemEvent事件,事件监事件,事件监视器接口为视器接口为ItemListener接口,该接口接口,该接口中的抽象方法为:中的抽象方法为:publicvoiditemStateChanged(ItemEvente)其中,其中,ItemEvent类提供以下两种方法:类提供以下两种方法:ItemSelectablegetItemSelectable()intgetStateChange()本章小结(续)选择框(也被称为复选框)提供两种状态,一种是选中,另一种是未选选择框(也被称为复选框)提供两种状态,一种是选中,另一种是未选中,实现用户的多种选择。选择框上发生的事件、接口及需要实现的方中,实现用户的多种选择。选择框上发生的事件、接口及需要实现的方法和法和JRadioButton相同。相同。菜单分为两类,一类是固定的,一类是弹出式菜单。菜单分为两类,一类是固定的,一类是弹出式菜单。固定的菜单是图形界面中最常用的一种菜单形式。固定菜单一般包括固定的菜单是图形界面中最常用的一种菜单形式。固定菜单一般包括菜单条、菜单组和菜单项。创建一个固定菜单分创建菜单条、创建菜单,菜单条、菜单组和菜单项。创建一个固定菜单分创建菜单条、创建菜单,将菜单加入菜单条、创建菜单项实现用户需要的功能,将菜单项加入菜将菜单加入菜单条、创建菜单项实现用户需要的功能,将菜单项加入菜单三步。单三步。JMenubar类负责创建菜单条,菜单条将被添加到窗口的顶端。类负责创建菜单条,菜单条将被添加到窗口的顶端。JMenubar菜单条不具备菜单条不具备Windows特性,它也不具备顶层容器类的特性,特性,它也不具备顶层容器类的特性,即不能独立显示出来,需要依赖顶层容器。即不能独立显示出来,需要依赖顶层容器。JMenu类负责创建菜单,菜单使用类负责创建菜单,菜单使用add()方法被放在菜单条里。方法被放在菜单条里。JMenuItem类负责创建菜单项,菜单项使用类负责创建菜单项,菜单项使用add()方法被放在菜单里。方法被放在菜单里。菜单项上可以发生菜单项上可以发生ActionEvent,其接口及实现方法和,其接口及实现方法和JButton相同。相同。本章小结(续)弹出式菜单的建立与普通菜单类似,但可以不需要加标题。创建弹出弹出式菜单的建立与普通菜单类似,但可以不需要加标题。创建弹出式菜单的步骤分创建一个空的弹出式菜单、将菜单项添加到弹出式菜单式菜单的步骤分创建一个空的弹出式菜单、将菜单项添加到弹出式菜单中、在容器中添加鼠标右键事件的处理代码三步。中、在容器中添加鼠标右键事件的处理代码三步。 JApplet类继承了类继承了Applet类,而类,而Applet类是类是Panel类的子类。通过继承类的子类。通过继承javax.swing.JApplet来实现来实现Applet编程。在编程。在JavaApplet中,可以实现中,可以实现图形绘制、字体和颜色控制、动画和声音的插入、人机交互及网络交流图形绘制、字体和颜色控制、动画和声音的插入、人机交互及网络交流等功能。等功能。一个一个JavaApplet程序中必须有一个类是程序中必须有一个类是Applet类的子类,该子类是类的子类,该子类是JavaApplet程序的主类,并且主类必须修饰为程序的主类,并且主类必须修饰为public的。的。Applet程序是程序是一种不能单独运行但可嵌入在其他应用程序中的小程序。一种不能单独运行但可嵌入在其他应用程序中的小程序。Applet类提供类提供了了JavaApplet程序及其运行环境之间的标准接口。程序及其运行环境之间的标准接口。JavaApplet应用程序的生命周期相对于应用程序的生命周期相对于Application而言较为复杂。在而言较为复杂。在JavaApplet的生命周期中,共有初始态、运行态、停止态和消亡态四种的生命周期中,共有初始态、运行态、停止态和消亡态四种状态。状态。借助借助Applet的的“画笔画笔”(Graphics)对象可调用各种方法实现各类图形)对象可调用各种方法实现各类图形的绘制。的绘制。Java程序设计基础与实践 第第9章章输入输入/输出操作输出操作本章导读Java应用不是一潭死水,经常需要和外应用不是一潭死水,经常需要和外界通信。界通信。流是一个很形象的概念,当程序需要读流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件、内存源的流,这个数据源可以是文件、内存或是网络连接。当程序需要写入数据的或是网络连接。当程序需要写入数据的时候,就会开启一个通向目的地的流。时候,就会开启一个通向目的地的流。Java语言中输入语言中输入/输出功能是通过流类来输出功能是通过流类来实现的,通过流,可以让数据以与设备实现的,通过流,可以让数据以与设备无关的方式流动,提高程序的通用性。无关的方式流动,提高程序的通用性。 本章要点Java输入输出流分类输入输出流分类Java字节流、字符流、过滤流字节流、字符流、过滤流Java文件操作类文件操作类Java标准输入输出流标准输入输出流Java对象序列化机制对象序列化机制 9.1基础知识9.1.1Java输入输入/输出概述输出概述Java流分很多种。按照流中数据流动的方向,可分为流分很多种。按照流中数据流动的方向,可分为输入流和输出流,若数据是从程序外部流入程序内部,输入流和输出流,若数据是从程序外部流入程序内部,则称为输入流,若从程序内部流到程序外部,则称为输则称为输入流,若从程序内部流到程序外部,则称为输出流;按照流数据处理的基本单位,可分为字节流和字出流;按照流数据处理的基本单位,可分为字节流和字符流,若流中数据的基本单位是字节,则称为字节流,符流,若流中数据的基本单位是字节,则称为字节流,若基本单位是字符,则称为字符流;按照流功能的不同,若基本单位是字符,则称为字符流;按照流功能的不同,可分为节点流和处理流,若流是直接从特定设备读出的,可分为节点流和处理流,若流是直接从特定设备读出的,例如从磁盘或者内存读出,那么叫做节点流,使用节点例如从磁盘或者内存读出,那么叫做节点流,使用节点流作为输入或者输出的流叫做处理流,也叫过滤流,或流作为输入或者输出的流叫做处理流,也叫过滤流,或者转换流。者转换流。下面介绍几种重要的输入输出流和下面介绍几种重要的输入输出流和Java提供的输入输提供的输入输出类。出类。9.1.2字节流InputStram和和OutputStream是是java.io包包中定义的两个抽象类,是所有字节流的父中定义的两个抽象类,是所有字节流的父类。类。InputStream类类InputStream是基本的输入流类,它是一是基本的输入流类,它是一个抽象类,它定义了输入流类共同的特性,个抽象类,它定义了输入流类共同的特性,是所有字节输入流的父类,字节输入流类是所有字节输入流的父类,字节输入流类的继承关系如图的继承关系如图9.1所示。所示。 InputStream类常用方法方法说明available()返回当前输入流的数据读取方法可以读取的有效字节数量read()从输入流的当前位置处读入一个字节(8位)的二进制数据,如果输入流的当前位置没有数据,则返回1read(byteb,b)从输入流读取字节并存入数组b,返回读入的字节数目read(byteb,b,intoffset,intlen)从输入流读取从第offset个字节开始长度为len的字节并存入数组bclose()关闭输入流并释放资源markSupperted()返回布尔值,说明输入流能否做标记skip(longn)将指针从当前位置向后跳动n个字节mark()在指针位置做一个标记。mark(intreadlimit)为当前流做标记,其参数说明在标记失效前可以读多少字节,这个值通常也设定了流的缓冲区大小reset()将指针移动到最后一次调用mark()方法的标记位置OutputStream类OutputStream是所有表示输出流的父类,是所有表示输出流的父类,它是一个抽象类,它定义了输出流类共它是一个抽象类,它定义了输出流类共同的特性,是锁有字节输出流的父类同的特性,是锁有字节输出流的父类 OutputStream类常用方法方法说明write(intb)参数b的低位字节写入输出流write(byteb)将byte型数组b中的全部字节顺序写入到输出流write(byteb,intoffset,intlen)将byte型数组b中从第offset个字节开始长度为len的字节顺序写入到输出流flush()强制清空缓冲区,并将缓冲区中的现有数据输出close()关闭输出流并释放资源FileInputStream类Java提供了专门的类对文件进行输入输提供了专门的类对文件进行输入输出操作。例如出操作。例如FileInputStream和和FileOutputStream,这两个类都属于字,这两个类都属于字节流,它们对数据进行读写的基本单位节流,它们对数据进行读写的基本单位是字节。是字节。FileInputStream类是类是InputStream的子的子类,它实现了对文件的读取,是文件字类,它实现了对文件的读取,是文件字节输入流。节输入流。 FileInputStream类常用构造方法构造方法说明FileInputStream(StringfilePath)根据filePath指定的文件名称和路径创建FileIutputStream类实例对象FileInputStream(Filefile)使用File类型的文件对象创建FileIutputStream类实例对象FileOutputStream类类FileOutputStream类是类是OnputStream的子类,的子类,它实现了对文件的写入,是文件字节输出流。它实现了对文件的写入,是文件字节输出流。构造方法说明FileOutputStream(StringfilePath)根据filePath指定的文件名称和路径创建FileOutputStream类实例对象FileOutputStream(Filefile)使用File类型的文件对象创建FileOutputStream类实例对象importjava.io.*;classReadWriteFilepublicstaticvoidmain(Stringargs)Stringfile1,file2;intch=0;file1=readme.txt;file2=readme.bak;tryFileInputStreamfis=newFileInputStream(file1);FileOutputStreamfos=newFileOutputStream(file2);intsize=fis.available();System.out.println(字节有效数:字节有效数:+size);while(ch=fis.read()!=-1)System.out.write(ch);fos.write(ch);fis.close();fos.close();catch(IOExceptione)System.out.println(e.toString();9.1.3字符流Reader类类Reader类是所有字符输入流的父类,提供了字类是所有字符输入流的父类,提供了字符输入流所有的基本功能,是所有字符输入流符输入流所有的基本功能,是所有字符输入流的父类。的父类。Reader类常用方法方法说明read()从输入流中读取一个字符,并返回读取的字符值,如果输入流的当前位置没有数据,则返回1read(charbuf)从输入流的当前位置处连续读入多个字符,保存到char型数组buf中,返回读入的字符数目skip(longn)将指针从当前位置向后跳动n个字节mark()在指针位置做一个标记reset()将指针移动到最后一次调用mark()的标记位置close()关闭输入流并释放资源Writer类类Writer是所有字符输出流的父类,提供是所有字符输出流的父类,提供了字符输出流的所有基本功能,是所有了字符输出流的所有基本功能,是所有字符输出流的父类字符输出流的父类 。Writer类常用方法方法说明write(charc)将参数c对应的字符写入输出流write(chararray)将字符数组array中的全部字符顺序写入到输出流write(charbuf,intoffset,intlen)将字符数组buf中从第offset个元素开始长度为len的字符顺序写入到输出流write(Strings)将字符串s写入输出流flush()强制清空缓冲区,并将缓冲区中的现有数据输出close()关闭输出流并释放资源InputStreamReader类类方法类型方法说明构造方法InputStreamReader(InputStreamin)使用默认字符集创建InputStreamReader类的实例对象InputStreamReader(InputStreamin,stringcname)使用已命名的字符编码方式cname创建InputStreamReader类的实例对象成员方法close()关闭流read()读取单个字符read(charb,intoffset,intlen)读取从第offset个字节开始长度为len的字符并存入数组bgetEncoding()返回此流使用的字符编码名称ready()返回是否准备读取此流InputStreamReader类是字节流到字符类是字节流到字符流的转换桥类,它可以根据指定的编码流的转换桥类,它可以根据指定的编码方式,将字节输入流转换为字符输入流。方式,将字节输入流转换为字符输入流。 OnputStreamWriter类类OnputStreamWriter类是字节流到字符流类是字节流到字符流的转换桥类,它可以的转换桥类,它可以根据指定的编码方式,根据指定的编码方式,将字节输出流转换为将字节输出流转换为字符输出流。字符输出流。方法类型方法说明构造方法OnputStreamWriter(OnputStreamout)使用默认字符集创建OnputstreamWriter类的实例对象OnputStreamWriter(OnputStreamout,stringcname)使用已命名的字符编码方式cname创建OnputstreamWriter类的实例对象成员方法close()关闭流,但要先刷新write(intb)写入单个字符到输出流write(Stringstr,intoffset,intlen)将字符串str中从第offset个字节开始长度为len的字符顺序写入到输出流write(charb,intoffset,intlen)将char型数组b中从第offset个字节开始长度为len的字符顺序写入到输出流flush()刷新流的缓冲importjava.io.*;publicclassStreamReaderWriterDemopublicstaticvoidmain(Stringargs)tryFilefile=newFile(args0);FileInputStreamfileInputStream=newFileInputStream(file);/为为FileInputStream加上字符处理功能加上字符处理功能InputStreamReaderinputStreamReader=newInputStreamReader(fileInputStream);FileOutputStreamfileOutputStream=newFileOutputStream(backup_+args0);/为为FileOutputStream加上字条处理功能加上字条处理功能OutputStreamWriteroutputStreamWriter=newOutputStreamWriter(fileOutputStream);intch=0;/以字符方式显示文件内容以字符方式显示文件内容while(ch=inputStreamReader.read()!=-1)System.out.print(char)ch);outputStreamWriter.write(ch);System.out.println();inputStreamReader.close();outputStreamWriter.close();catch(ArrayIndexOutOfBoundsExceptione)System.out.println(没有指定文件没有指定文件);catch(IOExceptione)e.printStackTrace();FileReader类类FileReader类是类是Reader类的子类,它实现了从类的子类,它实现了从文件中读出字符数据,是文件的字符输入流。文件中读出字符数据,是文件的字符输入流。构造方法说明FileReader(StringfilePath)根据filePath指定的文件名称和路径创建FileReader类实例对象FileReader(Filefile)使用File类型的文件对象创建FileReader类实例对象FileWriter类类FileWriter类是类是Writer类的子类,它类的子类,它实现了将字符数据写实现了将字符数据写入文件中,是文件的入文件中,是文件的字符输出流。字符输出流。构造方法说明FileWriter(StringfilePath)根据filePath指定的文件名称和路径创建FileWriter类实例对象FileWriter(Filefile)使用File类型的文件对象创建FileWriter类实例对象importjava.io.*;classFileWriterDemopublicstaticvoidmain(Stringargs)throwsExceptionStringsource=Nowisthetimeforallgoodmenn+tocometotheaidoftheircountryn+andpaytheirduetaxes.;charbuffer=newcharsource.length();source.getChars(0,source.length(),buffer,0);FileWriterf0=newFileWriter(file1.txt);for(inti=0;ibuffer.length;i+=2)f0.write(bufferi);f0.close();FileWriterf1=newFileWriter(file2.txt);f1.write(buffer);f1.close();FileWriterf2=newFileWriter(file3.txt);f2.write(buffer,buffer.length-buffer.length/4,buffer.length/4);f2.close();BufferedReader类类BufferedReader类是类是Reader类的子类,使用该类的子类,使用该类可以以行为单位读取数据。类可以以行为单位读取数据。方法类型方法说明构造方法BufferedReader(Readerin)使用Reader类对象创建BufferedReader类实例对象成员方法readerLine()读取一行数据BufferedWriter类类BufferedWriter类是类是Writer类的子类,使类的子类,使用该类可以以行为单用该类可以以行为单位写入数据。位写入数据。方法类型方法说明构造方法BufferedWriter(Writerout)使用Writer类对象创建BufferedWriter类实例对象成员方法newLine()换行importjava.util.*;importjava.io.*;publicclassBufferedReaderWriterDemopublicstaticvoidmain(Stringargs)try/缓冲缓冲System.in输入流输入流/System.in是位流,可以通过是位流,可以通过InputStreamReader将其转换为字符流将其转换为字符流BufferedReaderbufReader=newBufferedReader(newInputStreamReader(System.in);/缓冲缓冲FileWriterBufferedWriterbufWriter=newBufferedWriter(newFileWriter(args0);Stringinput=null;/每读一行进行一次写入动作每读一行进行一次写入动作while(!(input=bufReader.readLine().equals(quit)bufWriter.write(input);/newLine()方法写入与操作系统相依的换行字符,依执行环境当时的方法写入与操作系统相依的换行字符,依执行环境当时的OS来决定该输出那种换行字符来决定该输出那种换行字符bufWriter.newLine();bufReader.close();bufWriter.close();catch(ArrayIndexOutOfBoundsExceptione)System.out.println(没有指定文件没有指定文件);catch(IOExceptione)e.printStackTrace();PrintWriter类类PrintWriter类是打印类是打印输出流,该流把输出流,该流把Java语言的内构类型以字语言的内构类型以字符形式输出到相应的符形式输出到相应的输出流中,可以以文输出流中,可以以文本方式浏览。本方式浏览。方法类型方法说明构造方法printWriter(Writerout)使用Writer类对象创建PrintWriter类实例对象printWriter(outputStreamout)使用outputStream类对象创建PrintWriter类实例对象成员方法print(Stringstr)打印字符串数据print(inti)打印整型数据flush()强制将缓冲区数据输出println(Stringstr)打印字符串数据并换行println(inti)打印整型数据并换行println()打印换行importjava.io.*;publicclassPrintWriterDemopublicstaticvoidmain(Stringargs)throwsFileNotFoundExceptionStrings;tryBufferedReaderin=newBufferedReader(newStringReader(ttt.txt);PrintWriterout=newPrintWriter(newBufferedWriter(newFileWriter(IODemo.out);intlineCount=1;while(s=in.readLine()!=null)out.println(lineCount+:+s);out.close();catch(EOFExceptione)System.err.println(Endofstream);catch(IOExceptione)e.printStackTrace();9.1.4过滤流过滤器流是为某种目的过滤字节或字符的过滤器流是为某种目的过滤字节或字符的数据流。基本输入流提供的读取方法只能数据流。基本输入流提供的读取方法只能用来读取字节或字符,而过滤器流能够读用来读取字节或字符,而过滤器流能够读取整型、双精度值和字符串,但需要一个取整型、双精度值和字符串,但需要一个过滤流类来包装输入流。过滤流类来包装输入流。Java中定义了很多过滤流,例如中定义了很多过滤流,例如BufferedOutputStream和和BufferedInputStream、 DataOutputStream和和DataInputStream及及PrintStream等。每一种过滤流都有自等。每一种过滤流都有自己适合使用的场所。己适合使用的场所。DataInputStream类类DataInputStream类是类是InputStream子类子类FilterInputStream的子类,实现的子类,实现DataInput接口,可以使一个应用程序以接口,可以使一个应用程序以与机器无关的方式从基本输入流中读取与机器无关的方式从基本输入流中读取 Java的基本数据类型。的基本数据类型。 DataInputStream类常用方法方法类型方法说明构造方法DataInputStream(InputStreamin)创建一个新的数据输入流,从指定输入流中读取数据成员方法read(byteb)将当前数据输入流中b.length个字节数据读到一个字节数组b中read(byteb,intoffsetintlen)将当前数据输入流中从第offset个开始长度为len个字节数据读入一个字节数组b中readBoolean()从当前数据输入流中读取一个boolean值readByte()从当前数据输入流中读取一个有符号的8位数readChar()从当前数据输入流中读取一个Unicode字符readDouble()从当前数据输入流中读一个double值readFloat()从当前数据输入流中读一个float值readFully(byteb)从当前数据输入流中读取b.length个字节到该字节数组b中readFully(byteb,intoffset,intlen)从当前数据输入流中恰好读取从第offset个开始长度为len个字节到该字节数组b中readInt()从当前数据输入流中读取一个有符号的32位整数readLong()从当前数据输入流中读取一个有符号的64位整数readShort()从当前数据输入流中读取一个有符号的16位数readUnsignedByte()从当前数据输入流中读取一个无符号的8位数readUnsignedShort()从当前数据输入流中读取一个无符号的16位数readUTF()从当前数据输入流中读取一个已用“修订的UTF-8格式”编码的字符串readUTF(DataInputin)从指定的数据输入流in中读取一个字符串skipBytes(intn)准确地跳过基本输入流中n字节DataOutputStream类类DataOutputStream类是类是OutputStream子类子类FilterOutputStream的子类,实现的子类,实现DataOnput接口,可以使一个应用程序接口,可以使一个应用程序以与机器无关的方式从基本输入流中读以与机器无关的方式从基本输入流中读取取 Java的基本数据类型。的基本数据类型。 DataOutputStream类常用方法方法类型方法说明构造方法DataOutputStream(OutputStreamout)创建一个新的数据输出流,向指定的基本输出流写入数据成员方法flush()刷新当前数据输出流size()返回写入当前数据输出流的字节数write(byteb,intoffset,intlen)将指定的字节数组中从offset开始的len个字节,写到基本输出流bwrite(int)将指定字节写入基本输出流writeBoolean(boolean)将一boolean作为一字节值,写入该基本输出流writeByte(int)将一byte作为一字节值,写入该基本输出流writeBytes(String)将此串作为一个字节序列写入该基本输出流writeChar(int)将一char作为两字节值,写入该基本输出流,高字节优先writeChars(String)将此串作为一个字符序列写入该基本输出流writeDouble(double)使用类Double中doubleToLongBits方法,将给定的双精度浮点数转换为long值,然后将它当作一个8字节数写入该基本输出流,高字节优先。writeFloat(float)使用类Float中floatToIntBits方法,将给定的单精度浮点数转换为int值,然后将它当作一个4字节数写入该基本输出流,高字节位优先writeInt(int)将一int作为四字节值,写入该基本输出流,高字节优先writeLong(long)将一long作为八字节值,写入该基本输出流,高字节优先writeShort(int)将一short作为两字节值,写入该基本输出流,高字节优先writeUTF(String)使用独立于机器的UTF-8编码格式,将一个串写入该基本输出流importjava.io.*;publicclassDataStreamDemopublicstaticvoidmain(Stringargs)Membermembers=newMember(Justin,90),newMember(momor,95),newMember(Bush,88);tryDataOutputStreamdataOutputStream=newDataOutputStream(newFileOutputStream(args0);for(Membermember:members)dataOutputStream.writeUTF(member.getName();/写入写入UTF字符串字符串dataOutputStream.writeInt(member.getAge();/写入写入int数据数据dataOutputStream.flush();/所有数据至目的地所有数据至目的地dataOutputStream.close();/关闭流关闭流 DataInputStreamdataInputStream=newDataInputStream(newFileInputStream(args0);/读出数据并还原为对象读出数据并还原为对象for(inti=0;imembers.length;i+)Stringname=dataInputStream.readUTF();/读出读出UTF字符串字符串 intscore=dataInputStream.readInt();/读出读出int数据数据membersi=newMember(name,score);dataInputStream.close();/关闭流关闭流/显示还原后的数据显示还原后的数据for(Membermember:members)System.out.printf(%st%d%n,member.getName(),member.getAge();catch(IOExceptione)e.printStackTrace();classMemberprivateStringname;privateintage;publicMember(Stringname,intage)this.name=name;this.age=age;publicvoidsetName(Stringname)this.name=name;publicvoidsetAge(intage)this.age=age;publicStringgetName()returnname;publicintgetAge()returnage;BufferedInputStream类类BufferedInputStream类是类是InputStream子类子类FilterInputStream的子类,实现的子类,实现Closeable接口。作为另一种输入流,创接口。作为另一种输入流,创建建 BufferedInputStream时即创建了一时即创建了一个内部缓冲区数组,可以在此缓冲区进个内部缓冲区数组,可以在此缓冲区进行数据操作。行数据操作。 BufferedInputStream类常用方法方法类型方法说明构造方法BufferedInputStream(InputStreamin)创建一个新的数据输入缓冲流,从指定输入流中读取数据BufferedInputStream(InputStreamin,intsize)创建一个新的数据输入缓冲流,并指定其大小,从指定输入流中读取数据成员方法available()返回可以不受阻塞地从此输入流读取的字节数close()关闭此输入流并释放与该流关联的所有系统资源mark(intreadlimit)为当前流做标记,其参数说明在标记失效前可以读多少字节,这个值通常也设定了流的缓冲区大小markSupported()测试此输入流是否支持mark和reset方法read()从输入流的当前位置处读入一个字节(8位)的二进制数据,如果输入流的当前位置没有数据,则返回1read(byteb,intoffset,intlen)从输入流读取从第offset个字节开始长度为len的字节并存入数组breset()将指针移动到最后一次调用mark()方法的标记位置skip(longn)将指针从当前位置向后跳动n个字节BufferedOutputStream类类BufferedOutputStream类是类是OutputStream子类子类FilterOutputStream的子类,实现的子类,实现Closeable和和Flushable接接口。该类实现缓冲的输出流。口。该类实现缓冲的输出流。 BufferedOutputStream类常用方法方法类型方法说明构造方法BufferedOutputStream(OutputStreamout)创建一个新的缓冲输出流,以将数据写入指定输出流outBufferedOutputStream(OutputStreamout,intsize)创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定输出流out成员方法flush()刷新此缓冲的输出流write(byteb,intoffset,intlen)将指定byte数组中从偏移量offset开始的len个字节写入此缓冲的输出流write(intb)将指定的字节写入此缓冲的输出流importjava.io.*;publicclassBufferedStreamDemopublicstaticvoidmain(Stringargs)trybytedata=newbyte1;FilesrcFile=newFile(args0);FiledesFile=newFile(args1);BufferedInputStreambufferedInputStream=newBufferedInputStream(newFileInputStream(srcFile);BufferedOutputStreambufferedOutputStream=newBufferedOutputStream(newFileOutputStream(desFile);System.out.println(复制文件:复制文件:+srcFile.length()+字节字节);while(bufferedInputStream.read(data)!=-1)bufferedOutputStream.write(data);/将缓冲区中的数据全部写出将缓冲区中的数据全部写出bufferedOutputStream.flush();/关闭流关闭流bufferedInputStream.close();bufferedOutputStream.close();System.out.println(复制完成复制完成);catch(ArrayIndexOutOfBoundsExceptione)System.out.println(using:javaUseFileStreamsrcdes);e.printStackTrace();catch(IOExceptione)e.printStackTrace();PrintStream类类PrintStream类是打类是打印输出流,它可以直印输出流,它可以直接输出各种类型的数接输出各种类型的数据。据。方法类型方法说明构造方法printStream(outputStreamout)使用outputStream类对象创建PrintStream类实例对象成员方法print(Stringstr)打印字符串print(charch)打印字符数组print(objectobj)打印对象println(Stringstr)打印字符串并换行println(charch)打印字符数组并换行println(objectobj)打印对象并换行importjava.io.*;publicclassPrintStreamDemopublicstaticvoidmain(Stringargs)throwsFileNotFoundExceptionPrintStreamprintStream=newPrintStream(newFileOutputStream(newFile(test.txt);printStream.println(1);printStream.close();9.1.5Java对文件的操作Java提供提供File类、类、FileFilter接口、接口、FilenameFilter接口和接口和RandomAccessFile类对文件进行操作。类对文件进行操作。File类类File类提供了对文件和文件夹进行创建、类提供了对文件和文件夹进行创建、删除等基本操作。删除等基本操作。 File类的常用方法方法类型方法说明构造方法File(Fileparent,Stringchild)根据已有File类的对象parent和子路径child字符串创建一个新File对象。并且,要求parent是一个指向磁盘上存在的文件夹的File类对象File(Stringpathname)通过将给定路径名字符串pathname转换成抽象路径名来创建一个新File实例File(Stringparent,Stringchild)根据parent路径名字符串和child路径名字符串创建一个新File实例成员方法canRead()测试应用程序是否可以读取此抽象路径名表示的文件canWrite()测试应用程序是否可以修改此抽象路径名表示的文件compareTo(Filepathname)按字母顺序比较两个抽象路径名createNewFile()当且仅当不存在具有此抽象路径名指定的名称的文件时,创建由此抽象路径名指定的一个新的空文件createTempFile(Stringprefix,Stringsuffix)在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称createTempFile(Stringprefix,Stringsuffix,Filedirectory)在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称delete()删除此抽象路径名表示的文件或目录equals(Objectobj)测试此抽象路径名与给定对象是否相等exists()测试此抽象路径名表示的文件或目录是否存在getAbsoluteFile()返回抽象路径名的绝对路径名形式getAbsolutePath()返回抽象路径名的绝对路径名字符串getName()返回由此抽象路径名表示的文件或目录的名称getParent()返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回nullgetParentFile()返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回nullgetPath()将此抽象路径名转换为一个路径名字符串isAbsolute()测试此抽象路径名是否为绝对路径名isDirectory()测试此抽象路径名表示的文件是否是一个目录isFile()测试此抽象路径名表示的文件是否是一个标准文件length()返回由此抽象路径名表示的文件的长度list()返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组list(FilenameFilterfilter)返回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的listFiles()返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件listFiles(FileFilterfilter)返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器listFiles(FilenameFilterfilter)返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器listRoots()列出可用的文件系统根目录mkdir()创建此抽象路径名指定的目录mkdirs()创建此抽象路径名指定的目录,包括创建必需但不存在的父目录renameTo(Filedest)重新命名此抽象路径名表示的文件setLastModified(longtime)设置由此抽象路径名所指定的文件或目录的最后一次修改时间setReadOnly()标记此抽象路径名指定的文件或目录,以便只可对其进行读操作toString()返回此抽象路径名的路径名字符串importjava.io.*;importjava.util.Date;publicclassfiletestpublicstaticvoidmain(Stringargs)Stringfilename=e:javabook第第1题题.txt;Filemyfile=newFile(filename);if(!myfile.exists()System.err.println(filename+未找到未找到!);return;if(myfile.isDirectory()System.err.println(文件对象文件对象+myfile.getName()+是目录是目录!);Fileds=newFile(mydata);if(!ds.exists()ds.mkdir();System.out.println(目录目录+ds.getAbsolutePath()+创建结束创建结束!);return;if(myfile.isFile()System.out.println(文件对象文件对象:+myfile.getAbsolutePath();System.out.println(文件字节数文件字节数:+myfile.length();System.out.println(文件是否能读文件是否能读:+myfile.canRead();if(myfile.canWrite()System.out.println(设置文件为只读设置文件为只读:+myfile.setReadOnly();System.out.println(文件是否可写文件是否可写:+myfile.canWrite();Datefd=newDate(myfile.lastModified();System.out.println(文件上次修改时间文件上次修改时间:+fd.toString();FileFilter接口接口FileFilter接口用于过滤抽象路径名,此接口的接口用于过滤抽象路径名,此接口的实例可传递给实例可传递给File类的类的listFiles(FileFilter)方法。方法。方法说明accept(Filepathname)测试指定抽象路径名是否包含在某个路径名列表中FilenameFilter接口接口FilenameFilter接口接口用于过滤器抽象文件用于过滤器抽象文件名。就像名。就像Windows经经常使用的打开文件窗常使用的打开文件窗口,可以通过其口,可以通过其“文文件类型件类型”下拉列表查下拉列表查看当前目录下特定类看当前目录下特定类型的文件。这种功能型的文件。这种功能就是使用文件过滤器就是使用文件过滤器实现的。实现的。方法说明accept(Filedir,Stringname)测试指定文件是否包含在某一文件列表中RandomAccessFile类类使用使用RandomAccessFile类可以读取文类可以读取文件任意位置的数据,件任意位置的数据,RandomAccessFile类有一个指针,用类有一个指针,用于确定文件读写的位置。于确定文件读写的位置。RandomAccessFile类既不是输入流的类既不是输入流的子类,也不是输出流的子类,该类既可子类,也不是输出流的子类,该类既可以进行文件的输入操作,也可以进行文以进行文件的输入操作,也可以进行文件的输出操作。件的输出操作。 RandomAccessFile类常用方法方法类型方法说明构造方法RandomAccessFile(Filefile,Stringmode)在特定文件上建立RandomAccessFile流,该文件由File类对象file指定RandomAccessFile(Stringname,Stringmode)在特定文件上建立RandomAccessFile流,该文件由字符串name指定,参数mode表示流访问文件的模式,可以取以下值:“r”以只读方式打开,调用结果对象的任何write方法都将导致抛出IOException。“rw”打开以便读取和写入,如果该文件尚不存在,则尝试创建该文件成员方法length()返回文件长度seek(longpos)设置文件指针位置getFilePointer()获取指针的当前位置readByte()从文件读取一个字节readChar()从文件读取一个字符readInt()从文件读取一个int值readLine()从文件读取一个文本行readBoolean()从文件读取一个布尔值readUTF()从文件读取一个UTF字符串writeInt(intv)向文件写入一个int值write(bytebytes)把bytes.length字节写入文件writeChars(Stringstr)向文件写入一个字符数据类型的字符串writeUTF(Stringstr)向文件写入一个UTF类型的字符串close()关闭文件importjava.io.IOException;importjava.io.File;importjava.io.RandomAccessFile;publicclassRandomFileTestpublicstaticvoidmain(Stringargs)throwsExceptionStudents1=newStudent(1,zhangsan,90.5);Students2=newStudent(2,lisi,98.5);Students3=newStudent(3,wangwu,96.5);FileuserDir=newFile(System.getProperties().getProperty(user.dir);FiletempFile=File.createTempFile(student,.tmp,userDir);tempFile.deleteOnExit();RandomAccessFileraf=newRandomAccessFile(tempFile,rw);s1.write(raf);s2.write(raf);s3.write(raf);raf.seek(0);Students=newStudent();for(longi=0;iraf.length();i=raf.getFilePointer()s.read(raf);System.out.println(lenth:+raf.length()+,i=+i+s);raf.close();Thread.sleep(5000);classStudentintnum;Stringname;doublescore;publicStudent()publicStudent(intnum,Stringname,doublescore)this.num=num;this.name=name;this.score=score;publicvoidwrite(RandomAccessFileraf)throwsIOExceptionraf.writeInt(num);raf.writeUTF(name);raf.writeDouble(score);publicvoidread(RandomAccessFileraf)throwsIOExceptionnum=raf.readInt();name=raf.readUTF();score=raf.readDouble();publicStringtoString()returnnum=+num+,name=+name+,score=+score;9.1.6Scanner类和标准输入输出流Java使用使用Scanner类类和和System.in获取用户获取用户输入,使用输入,使用System.out输出用户输出用户信息。信息。Scanner类类Java5添加了添加了java.util.Scanner类,类,该类用来实现用户的该类用来实现用户的输入,是一种只要有输入,是一种只要有控制台就能够实现输控制台就能够实现输入操作的类。入操作的类。方法类型方法说明构造方法Scanner(Filesource)构造一个新的Scanner,它生成的值是从指定文件输入的Scanner(Filesource,StringcharsetName)构造一个新的Scanner,它生成的值是从指定文件输入的Scanner(InputStreamsource)构造一个新的Scanner,它生成的值是从指定的输入流输入的Scanner(InputStreamsource,StringcharsetName)构造一个新的Scanner,它生成的值是从指定的输入流输入的Scanner(Stringsource)构造一个新的Scanner,它生成的值是从指定字符串输入的成员方法close()关闭输入next()输入下一个nextLine()输入下一个并换行System.in和和System.outSystem.in是是System类的标准输入流,类的标准输入流,通常此流对应于键盘输入,通常此流对应于键盘输入,System.out是是System类的标准输出流,通常此流对类的标准输出流,通常此流对应于显示器输出或者由主机环境或用户应于显示器输出或者由主机环境或用户指定的另一个输出目标。指定的另一个输出目标。9.1.7对象序列化在一个程序运行的时候,其中的变量数据是保存在内在一个程序运行的时候,其中的变量数据是保存在内存中的,一旦程序结束这些数据将不会被保存,一种存中的,一旦程序结束这些数据将不会被保存,一种解决的办法是将数据写入文件,程序下次运行时读取解决的办法是将数据写入文件,程序下次运行时读取文件数据即可。但对于复杂的对象类型,使用文件方文件数据即可。但对于复杂的对象类型,使用文件方法则相对比较复杂,而法则相对比较复杂,而Java中提供了一种机制,它可中提供了一种机制,它可以将程序中的对象写入文件,之后再从文件中把对象以将程序中的对象写入文件,之后再从文件中把对象读出来重新建立,这就是所谓的对象序列化。读出来重新建立,这就是所谓的对象序列化。Java提供了提供了ObjectInput接口、接口、ObjectOutput接口,接口,接口中方法能进行对象序列化,接口中方法能进行对象序列化,Java提供了提供了ObjectInputStream类和类和ObjectOutputStream类读取类读取和保存对象数据。将一个对象存入一个流称为序列化,和保存对象数据。将一个对象存入一个流称为序列化,将一个对象从一个流读出称为反序列化。将一个对象从一个流读出称为反序列化。 9.1.7对象序列化ObjectInput接口接口ObjectInput接口继承了接口继承了DataInput接口,接口,提供了对象序列化的方法。提供了对象序列化的方法。ObjectOutput接口接口ObjectOutput接口继承了接口继承了DataOutput接接口,提供了对象反序列化的方法。口,提供了对象反序列化的方法。 9.1.7对象序列化ObjectInputStream类类ObjectInputStream类是类是InputStream类类的子类,的子类,ObjectInputStream对以前使对以前使用用 ObjectOutputStream写入的基本数写入的基本数据和对象进行反序列化。据和对象进行反序列化。 ObjectInputStream类常用方法方法类型方法说明构造方法ObjectInputStream(InputStreamin)创建从指定InputStream读取的ObjectInputStream成员方法readObject()从ObjectInputStream读取对象ObjectOutputStream类类ObjectOutputStream类是类是OutputStream类的类的子类,子类,ObjectOutputStream将对象序列化。将对象序列化。方法类型方法说明构造方法ObjectOutputStream(OutputStreamout)创建写入指定OutputStream的ObjectOutputStream成员方法writeObject(Objectobj)将对象写入基础存储或流Java程序设计基础与实践 第第10章章多线程编程多线程编程本章导读并发操作经常发生,例如,利用电脑听音乐时可以同时打印文档,并发操作经常发生,例如,利用电脑听音乐时可以同时打印文档,Java提供多线程编程实现并发操作。多线程与并发处理是程序设提供多线程编程实现并发操作。多线程与并发处理是程序设计好坏优劣的重要标志。计好坏优劣的重要标志。Java编写程序都运行在编写程序都运行在JVM中,在中,在JVM内部,每用内部,每用Java命令启命令启动一个动一个Java应用程序,就会启动一个应用程序,就会启动一个JVM进程。在同一个进程。在同一个JVM进进程中,有且只有一个进程,所有程序代码的运行都是以线程来运程中,有且只有一个进程,所有程序代码的运行都是以线程来运行。对于一个进程中的多个线程来说,多个线程共享进程的内存行。对于一个进程中的多个线程来说,多个线程共享进程的内存块,当有新的线程产生的时候,操作系统不分配新的内存,而是块,当有新的线程产生的时候,操作系统不分配新的内存,而是让新线程共享原有的进程块的内存。因此,线程间的让新线程共享原有的进程块的内存。因此,线程间的通信通信很容易,很容易,速度也很快。速度也很快。但并发操作有时可能会出现问题,例如,老师修改学生成绩时,但并发操作有时可能会出现问题,例如,老师修改学生成绩时,学生可能正在查询成绩,同一时间一个人往仓库中加货,另一个学生可能正在查询成绩,同一时间一个人往仓库中加货,另一个人从仓库中取货,这都是实际中经常发生的事情,如果控制不好人从仓库中取货,这都是实际中经常发生的事情,如果控制不好就会出现学生查询到的成绩不是老师修改后的成绩,仓库中货物就会出现学生查询到的成绩不是老师修改后的成绩,仓库中货物的总量统计不正确等问题,所以需要对并发操作进行控制。的总量统计不正确等问题,所以需要对并发操作进行控制。在在Java程序中,程序中,JVM负责线程的调度。负责线程的调度。 本章要点Java线程类和接口线程类和接口Java线程的创建方法线程的创建方法Java线程的生命周期线程的生命周期Java线程的优先权线程的优先权Java线程的同步和死锁线程的同步和死锁10.1基础知识10.1.1什么是多线程?什么是多线程?现在的操作系统是多任务操作系统,多线程是实现多任务的一种方式。现在的操作系统是多任务操作系统,多线程是实现多任务的一种方式。进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,显然,程序是死的、静态的,进程是活的、动态的。在内存空间,显然,程序是死的、静态的,进程是活的、动态的。在Windows下,进程又被细化为线程,也就是一个进程下有多个能独下,进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位。在立运行的更小的单位。在Windows中,中,CPU分配是以线程为单位的,分配是以线程为单位的,一个进程可由多个线程组成。通过在一个程序进程内部同时执行多个一个进程可由多个线程组成。通过在一个程序进程内部同时执行多个线程,可以充分利用线程,可以充分利用CPU等系统资源,从而最大限度的提高系统响应等系统资源,从而最大限度的提高系统响应速度。速度。对于操作系统而言,其调度单元是线程。一个进程至少包括一个线程,对于操作系统而言,其调度单元是线程。一个进程至少包括一个线程,通常将该线程称为主线程。一个进程从主线程的执行开始进而创建一通常将该线程称为主线程。一个进程从主线程的执行开始进而创建一个或多个附加线程,就是所谓基于多线程的多任务。个或多个附加线程,就是所谓基于多线程的多任务。多线程编程是程序设计技术中的一个很重要的领域,目前多数主流的多线程编程是程序设计技术中的一个很重要的领域,目前多数主流的操作系统都支持多任务操作。多线程是进行大型复杂软件系统开发的操作系统都支持多任务操作。多线程是进行大型复杂软件系统开发的一把利器。一把利器。10.1.2Thread类和Runnable接口Java中编程实现多线程有两种方法,一中编程实现多线程有两种方法,一是创建用户自己的线程子类,二是在用是创建用户自己的线程子类,二是在用户自己的类中实现户自己的类中实现Runnable接口。无论接口。无论哪种方法都需要使用哪种方法都需要使用Java基础类库中的基础类库中的Thread类及其方法。类及其方法。Thread类类Thread是是Java的线程类,该类定义了线的线程类,该类定义了线程所有的基本操作。程所有的基本操作。方法类型方法说明构造方法Thread()创建一个线程Thread(Stringname)创建一个名为name的线程Thread(Runnabletarget)创建一个线程,target称为被创建线程的目标对象,创建目标对象target的类负责实现Runable接口,给出改接口中run()方法的方法体Thread(Runnabletarget,Stringname)创建一个名为name的线程,创建目标对象target的类负责实现Runable接口Thread(ThreadGroupgroup,Runnabletarget)创建一个属于Group线程组的线程,其他同上Thread(ThreadGroupgroup,Runnabletarget,Stringname)创建一个属于Group线程组的线程,其他同上Thread(ThreadGroupgroup,Stringname)创建一个属于Group线程组的线程,其他同上Thread(ThreadGroupgroup,Runnabletarget,Stringname)创建一个属于Group线程组的线程,其他同上成员方法staticThreadcurrentThread()返回当前正在执行的线程对象StringgetName()返回该线程的名称intgetPriority()返回线程的优先级voidsetPriority(intnewpriority)设置线程的优先级,JavaThread类有3个关于线程优先级的静态常量:Thread.MAX_PRIORITY、Thread.MIN_PRIORITY、Thread.NORM_PRIORITY。其中MIN_PRIORITY优先级最小,通常为1,MAX_PRIORITY优先级最大,通常为10,NORM_PRIORITY为普通优先级,缺省值为5.voidinterrupt()中断线程booleanisAlive()返回线程是否处于活动状态booleanisInterrupted();返回线程是否处于阻塞状态voidsetName(Stringname)设置线程名字staticvoidsleep(longmillsecond)使当前线程睡眠指定时间,millsecond指定毫秒voidstart()使线程开始执行voidstop()使线程结束执行voidwait()使线程挂起voidnotify()唤醒等待序列中的某个线程voidnotifyAll()唤醒等待序列中的所有线程voidyelid()是当前线程停止,并把执行时间让给其他线程voidjoin()插入一个线程,当插入线程执行完毕后再接着执行被插入线程Runnable接口接口Runnable接口的定义如下:接口的定义如下:publicinterfaceJava.lang.Runnablepublicabstractvoidrun();由此可见由此可见Ruunnable接口中只有一个抽象方法接口中只有一个抽象方法run(),所有实现了,所有实现了Runnable接口的类都必须实现接口的类都必须实现run()方法。方法。Runnable接口中的接口中的run()方法可以被方法可以被运行时系统自动识别和执行,即当线程被调度运行时系统自动识别和执行,即当线程被调度并转入运行状态时,系统自动执行并转入运行状态时,系统自动执行run()方法中方法中的代码。的代码。 10.1.2创建线程通过通过Thread类创建线程类创建线程Thread类提供了一个类提供了一个publicvoidrun()方法,方法,该方法不执行任何操作,是线程的执行体。因该方法不执行任何操作,是线程的执行体。因此,此,Thread的子类应该重写该方法,以便于重的子类应该重写该方法,以便于重定义线程的执行体。定义线程的执行体。使用使用Thread类创建线程要遵循以下步骤:类创建线程要遵循以下步骤: 通过通过extendsThread类创建用户自己的线类创建用户自己的线程;程;重写重写run()方法;方法;创建用户自己线程类的对象并且调用创建用户自己线程类的对象并且调用start()方法使之进入就绪队列,等待运行。方法使之进入就绪队列,等待运行。 classTwoThreadsTestpublicstaticvoidmain(Stringargs)newSimpleThread(线程线程1).start();/创建用户自己线程类的对象,调用创建用户自己线程类的对象,调用start()方法方法newSimpleThread(线程线程2).start();/创建用户自己线程类的对象,调用创建用户自己线程类的对象,调用start()方法方法classSimpleThreadextendsThread/定义用户自己的线程类定义用户自己的线程类publicSimpleThread(Stringstr)/定义自己的构造方法定义自己的构造方法super(str);publicvoidrun()/重写重写run()方法方法for(inti=0;i10;i+)/循环方式调用线程循环方式调用线程System.out.println(i+getName();/利用利用Thread类的类的getName()方法得到方法得到线程名字线程名字trysleep(int)(Math.random()*1000);catch(InterruptedExceptione)System.out.println(DONE!+getName();10.1.2创建线程通过通过Runnable接口创建线程接口创建线程通过通过Runnable接口创建线程的步骤如下:接口创建线程的步骤如下:通过通过implementsRunnable接口创建接口创建用户自己的线程;用户自己的线程;重写重写run()方法;方法;通过通过Thread()的构造方法创建线程类的构造方法创建线程类对象并且调用对象并且调用start()方法使之进入就绪队方法使之进入就绪队列,等待运行。列,等待运行。 classTwoThreadsTestpublicstaticvoidmain(Stringargs)/通过通过Thread()构造方法创建用户自己线程类的对象,调用构造方法创建用户自己线程类的对象,调用start()方法方法newThread(newSimpleThread(线程线程1).start();newThread(newSimpleThread(线程线程2).start();classSimpleThreadimplementsRunnable/implementsRunnable接口接口Stringname=;/定义并获取线程名字定义并获取线程名字publicSimpleThread(Stringstr)/定义自己的构造方法定义自己的构造方法this.name=str;publicvoidrun()for(inti=0;i10;i+)System.out.println(i+name);tryThread.sleep(int)(Math.random()*1000);catch(InterruptedExceptione)System.out.println(DONE!+name);两种方法创建线程的不同两种方法创建线程的不同Thread和和Runnable实现线程是不同的。实现线程是不同的。采用实现采用实现Runnable接口创建线程首先应接口创建线程首先应定义一个实现定义一个实现Runnable接口的类,然后,接口的类,然后,把这个类的实例传给把这个类的实例传给Thread构造方法。构造方法。这样,新创建的这样,新创建的Thread对象共同拥有一对象共同拥有一个个Runnable实例,共享数据;采用继承实例,共享数据;采用继承Thread类的方法创建线程,实际上创建类的方法创建线程,实际上创建了不同的了不同的Thread对象,它们不共享数据。对象,它们不共享数据。classMyThreadextendsThreadpublicintx=0;publicvoidrun()System.out.println(+x);classRimplementsRunnableprivateintx=0;publicvoidrun()System.out.println(+x);publicclassTestpublicstaticvoidmain(Stringargs)for(inti=0;i10;i+)Threadt=newMyThread();t.start();Rr=newR();for(inti=0;i10;i+)Threadt=newThread(r);t.start();10.1.3线程的生命周期在在Java中,线程是对象。作为一个可以独立运行的对象,线程具有从出生中,线程是对象。作为一个可以独立运行的对象,线程具有从出生到死亡完整的生命周期,包括新建、就绪、运行、阻塞、死亡五个状态。到死亡完整的生命周期,包括新建、就绪、运行、阻塞、死亡五个状态。新建新建当线程对象在通过当线程对象在通过new运算符被创建时,这个线程就处于新建状态。处于新运算符被创建时,这个线程就处于新建状态。处于新建状态的线程,获得了自己运行所需的内存空间,但是却并不能被运行,因建状态的线程,获得了自己运行所需的内存空间,但是却并不能被运行,因为处于新建状态的线程不会获得为处于新建状态的线程不会获得CPU资源。资源。就绪就绪为了能够获得为了能够获得CPU资源,必须通过线程对象调用资源,必须通过线程对象调用start()方法,使线程对象进方法,使线程对象进入就绪队列,等待入就绪队列,等待CPU资源。处于就绪队列的线程被称为处于就绪状态。资源。处于就绪队列的线程被称为处于就绪状态。JVM管理着一个线程的就绪队列,管理着一个线程的就绪队列,CPU会从就绪队列中获取线程并加以执会从就绪队列中获取线程并加以执行。线程一旦进入了就绪队列,就完全脱离了程序员的控制,在行。线程一旦进入了就绪队列,就完全脱离了程序员的控制,在JVM的调的调度下运行,直至运行完毕。度下运行,直至运行完毕。运行运行处于就绪队列中的线程,当获得处于就绪队列中的线程,当获得CPU资源时,就会跳出就绪列表,开始执资源时,就会跳出就绪列表,开始执行行run()方法中的语句,进入运行状态。可以通过方法中的语句,进入运行状态。可以通过Thread类提供的类提供的isAlive()方法得知线程是否处于运行状态。方法得知线程是否处于运行状态。10.1.3线程的生命周期阻塞阻塞处于运行状态的线程,在某些情况下会进入阻塞状态。比如,线程要进行处于运行状态的线程,在某些情况下会进入阻塞状态。比如,线程要进行读写磁盘的操作,而这个操作相对来说比较慢,这种情况下线程应该阻塞,读写磁盘的操作,而这个操作相对来说比较慢,这种情况下线程应该阻塞,以便让其他的线程得以执行。处于阻塞状态的线程不会被以便让其他的线程得以执行。处于阻塞状态的线程不会被CPU运行,只有运行,只有重新进入就绪列表排队等待重新进入就绪列表排队等待CPU资源。资源。在以下情况下,线程会被阻塞:在以下情况下,线程会被阻塞:当前线程已经运行了足够长的时间,当前线程已经运行了足够长的时间,JVM将将CPU资源轮转给了其他线程,资源轮转给了其他线程,则当前线程进入就绪队列,等待再次被执行。则当前线程进入就绪队列,等待再次被执行。当前线程在运行过程中,主动调用当前线程在运行过程中,主动调用sleep(intmillsecond)方法,方法,Thread类类的的sleep()方法能够让当前执行的线程睡眠。在睡眠期间,线程会主动放弃方法能够让当前执行的线程睡眠。在睡眠期间,线程会主动放弃CPU的使用权,所以其他的线程可以获取到的使用权,所以其他的线程可以获取到CPU使用权继续运行。睡眠指使用权继续运行。睡眠指定定millsecond时间后线程自然醒来,重新进入就绪队列排队等候时间后线程自然醒来,重新进入就绪队列排队等候CPU资源。资源。在线程睡眠时候是可以由其他的线程调用某线程的在线程睡眠时候是可以由其他的线程调用某线程的interrupt()方法将该线方法将该线程强行唤醒的,被吵醒的线程会抛出程强行唤醒的,被吵醒的线程会抛出InterruptedException异常。在异常。在Java中,有时候抛出异常并不等于有错误发生,这里就是一个例子。这里抛出中,有时候抛出异常并不等于有错误发生,这里就是一个例子。这里抛出异常只是用于向系统说明,线程是被吵醒的,而不是自然醒来的。线程被异常只是用于向系统说明,线程是被吵醒的,而不是自然醒来的。线程被吵醒后,重新进入就绪队列排队等候吵醒后,重新进入就绪队列排队等候CPU资源。资源。当前线程在运行过程中,主动调用了当前线程在运行过程中,主动调用了wait()方法进入阻塞状态,直到其他方法进入阻塞状态,直到其他线程调用线程调用notify()或者或者notifyAll()方法将它唤醒,然后重新进入就绪列表,方法将它唤醒,然后重新进入就绪列表,排队等待被再次运行。排队等待被再次运行。10.1.3线程的生命周期死亡死亡所谓线程的死亡状态是指线程对象释放掉了自所谓线程的死亡状态是指线程对象释放掉了自己的实体部分,即释放掉了分配给线程对象的己的实体部分,即释放掉了分配给线程对象的内存。内存。线程的死亡原因分为线程的死亡原因分为“正常死亡正常死亡”和和“非正常非正常死亡死亡”两种。正常死亡是指线程执行了两种。正常死亡是指线程执行了run()方方法中的所有代码,完成了执行任务。这种情况法中的所有代码,完成了执行任务。这种情况下,线程会被系统释放掉。非正常死亡是指线下,线程会被系统释放掉。非正常死亡是指线程还没有完成自己的执行任务,被人为调用了程还没有完成自己的执行任务,被人为调用了stop()方法强制性地杀死了。由于强制杀死一个线方法强制性地杀死了。由于强制杀死一个线程会引起一些安全性的问题,因此在新版的程会引起一些安全性的问题,因此在新版的JDK中,该方法已经被建议不再使用。中,该方法已经被建议不再使用。 publicclassMultiThreadpublicstaticvoidmain(Stringargs)System.out.println(我是主线程我是主线程!);/下面创建线程实例下面创建线程实例thread1ThreadUseExtendsthread1=newThreadUseExtends();/创建创建thread2时以实现了时以实现了Runnable接口的接口的THhreadUseRunnable类实例为参数类实例为参数 Threadthread2=newThread(newThreadUseRunnable(),SecondThread);thread1.start();/启动线程启动线程thread1使之处于就绪状态使之处于就绪状态 System.out.println(主线程将挂起主线程将挂起7秒秒!);tryThread.sleep(7000);/主线程挂起主线程挂起7秒秒 catch(InterruptedExceptione)return;System.out.println(又回到了主线程又回到了主线程!);if(thread1.isAlive()thread1.stop();/如果如果thread1还存在则杀掉他还存在则杀掉他 System.out.println(thread1休眠过长休眠过长,主线程杀掉了主线程杀掉了thread1!);elseSystem.out.println(主线程没发现主线程没发现thread1,thread1已醒顺序执行结束了已醒顺序执行结束了!);thread2.start();/启动启动thread2System.out.println(主线程又将挂起主线程又将挂起7秒秒!);tryThread.sleep(7000);/主线程挂起主线程挂起7秒秒 catch(InterruptedExceptione)return;System.out.println(又回到了主线程又回到了主线程!);if(thread2.isAlive()thread2.stop();/如果如果thread2还存在则杀掉他还存在则杀掉他 System.out.println(thread2休眠过长,主线程杀掉了休眠过长,主线程杀掉了thread2!);elseSystem.out.println(主线程没发现主线程没发现thread2,thread2已醒顺序执行结束了已醒顺序执行结束了!);classThreadUseExtendsextendsThreadThreadUseExtends()/构造函数构造函数 publicvoidrun()System.out.println(我是我是Thread子类的线程实例子类的线程实例!);System.out.println(我将挂起我将挂起10秒秒!);trysleep(10000);/挂起挂起10秒秒 catch(InterruptedExceptione)return;classThreadUseRunnableimplementsRunnableThreadUseRunnable()/构造函数构造函数 publicvoidrun()System.out.println(我是我是Thread类的线程实例并以实现了类的线程实例并以实现了Runnable接口的类为参数接口的类为参数!);System.out.println(我将挂起我将挂起1秒秒!);tryThread.sleep(1000);/挂起挂起1秒秒 catch(InterruptedExceptione)return;10.1.4线程的优先权Java提供一个线程调度器来监控程序启动后进入就绪状态的所有提供一个线程调度器来监控程序启动后进入就绪状态的所有线程,线程调度器按照线程的优先级决定应调度哪个线程来执行,线程,线程调度器按照线程的优先级决定应调度哪个线程来执行,线程的优先级用数字表示,范围从线程的优先级用数字表示,范围从1到到10,一个线程的缺省优先,一个线程的缺省优先级是级是5。在线程优先级相同的情况下,在线程优先级相同的情况下,JVM对处于就绪队列中的线程采用对处于就绪队列中的线程采用先到先服务先到先服务(FCFS)的调度原则,也就是说哪个线程先进入的就绪的调度原则,也就是说哪个线程先进入的就绪队列,哪个线程会首先被队列,哪个线程会首先被JVM所执行。在优先级不同的情况下,所执行。在优先级不同的情况下,会优先考虑优先级。会优先考虑优先级。线程类线程类Thread提供了成员方法提供了成员方法publicvoidsetPriority(intpriority)来设置线程的优先级,使用来设置线程的优先级,使用publicintgetPriority()来获来获得线程的优先级。得线程的优先级。Thread定义了三个用于优先级的静态常量,可以通过类名直接调定义了三个用于优先级的静态常量,可以通过类名直接调用。分别是:用。分别是:MAX_PRIORITY/优先级为优先级为10MIN_PRIORITY/优先级为优先级为1NORM_PRIORITY/优先级为优先级为5classMyThreadextendsThreadStringname=;/定义并获取线程名字定义并获取线程名字publicMyThread(Stringstr)/定义自己的构造方法定义自己的构造方法this.name=str;publicintx=0;publicvoidrun()System.out.println(+x);System.out.println(name);classRimplementsRunnableStringname=;/定义并获取线程名字定义并获取线程名字publicR(Stringstr)/定义自己的构造方法定义自己的构造方法this.name=str;privateintx=0;publicvoidrun()System.out.println(+x);System.out.println(name);publicclassTestpublicstaticvoidmain(Stringargs)Rr=newR(runnable线程线程);for(inti=0;i10;i+)Threadt1=newMyThread(thread线程线程);Threadt2=newThread(r);t1.setPriority(1);t2.setPriority(10);t1.start();t2.start();10.1.5线程同步和锁同步问题提出同步问题提出 classFooprivateintx=100;publicintgetX()returnx;publicintfix(inty)x=x-y;returnx;publicclassMyRunnableimplementsRunnableprivateFoofoo=newFoo();publicstaticvoidmain(Stringargs)MyRunnabler=newMyRunnable();Threadta=newThread(r,Thread-A);Threadtb=newThread(r,Thread-B);ta.start();tb.start();publicvoidrun()for(inti=0;i3;i+)foo.fix(30);System.out.println(Thread.currentThread().getName()+当前当前foo对象的对象的x值值=+foo.getX();tryThread.sleep(1);catch(InterruptedExceptione)e.printStackTrace();同步和锁定同步和锁定在多个并发线程之间共用资源,就需要进行同步处理。在多个并发线程之间共用资源,就需要进行同步处理。Java虚拟机通过虚拟机通过给每个对象加锁的方式实现多线程的同步处理。给每个对象加锁的方式实现多线程的同步处理。Java中每个对象都有一个内置锁,当程序运行到同步方法代码时,自动中每个对象都有一个内置锁,当程序运行到同步方法代码时,自动获得该对象的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象获得该对象的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。上锁定或在对象上同步。 当程序运行到同步方法或代码块时才该对象锁当程序运行到同步方法或代码块时才该对象锁才起作用。才起作用。 一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到该线程释放(或返回)锁。这也意味着任何其他线程可以获得锁,直到该线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的同步方法或代码块,直到该锁被释放。都不能进入该对象上的同步方法或代码块,直到该锁被释放。 释放锁是释放锁是指持锁线程退出了同步方法或代码块。指持锁线程退出了同步方法或代码块。 在一个方法的前面加上修饰词在一个方法的前面加上修饰词synchronized该方法就成为同步方法。如该方法就成为同步方法。如果同步方法是静态方法,则相应的同步方法会与该方法所在的类对象相果同步方法是静态方法,则相应的同步方法会与该方法所在的类对象相关联,受类对象的控制,如果同步方法是非静态方法,则相应的同步方关联,受类对象的控制,如果同步方法是非静态方法,则相应的同步方法会和该方法所在的类的某个实例对象向关联,受该实例对象锁的控制。法会和该方法所在的类的某个实例对象向关联,受该实例对象锁的控制。如果多个同步方法与一个对象(类对象或实例对象)相关联,这些同步如果多个同步方法与一个对象(类对象或实例对象)相关联,这些同步方法都受这个对象锁的控制。在任何相同的时刻最多有一个线程进入这方法都受这个对象锁的控制。在任何相同的时刻最多有一个线程进入这个同步方法。个同步方法。同步不但可以同步整个方法,还可以同步方法中一部分代码块。其格式同步不但可以同步整个方法,还可以同步方法中一部分代码块。其格式如下:如下:synchronized(同步代码块(同步代码块 修改上面的例子,代码如下:修改上面的例子,代码如下:publicsynchronizedintfix(inty)x=x-y;returnx;关于同步和锁,需要注意以下几点:关于同步和锁,需要注意以下几点:只能同步方法,而不能同步变量和类;只能同步方法,而不能同步变量和类;不必同步类中所有的方法,类可以同时拥有同步和非同步方法,如不必同步类中所有的方法,类可以同时拥有同步和非同步方法,如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。访问而不受锁的限制。如果两个线程要执行一个类中的如果两个线程要执行一个类中的synchronized方法,并且两个线方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说,如果一个线程方法,另一个需要等待,直到锁被释放。也就是说,如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。类中的任何一个同步方法。线程睡眠时,它所持的任何锁都不会释放。线程睡眠时,它所持的任何锁都不会释放。 线程可以获得多个锁,例如,在一个对象的同步方法里面调用另外线程可以获得多个锁,例如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。一个对象的同步方法,则获取了两个对象的同步锁。同步锁损害并发性,应该尽可能缩小同步锁的使用范围。同步锁损害并发性,应该尽可能缩小同步锁的使用范围。 线程通信线程通信在在Java中线程的交互使用中线程的交互使用java.lang.Object的类的方的类的方法。法。 voidnotify(),唤醒在此对象监视器上等待的单个线,唤醒在此对象监视器上等待的单个线程。程。voidnotifyAll(),唤醒在此对象监视器上等待的所有,唤醒在此对象监视器上等待的所有线程。线程。voidwait(),导致当前的线程等待,直到其他线程调,导致当前的线程等待,直到其他线程调用此对象的用此对象的notify()方法或方法或notifyAll()方法。方法。 voidwait(longtimeout),导致当前的线程等待,直,导致当前的线程等待,直到其他线程调用此对象的到其他线程调用此对象的notify()方法或方法或 notifyAll()方方法,或者超过指定的时间量(法,或者超过指定的时间量(timeout)。)。voidwait(longtimeout,intnanos),导致当前的线,导致当前的线程等待,直到其他线程调用此对象的程等待,直到其他线程调用此对象的notify()方法或方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量(某个实际时间量(timeout毫秒值与毫秒值与nanos毫微秒参数毫微秒参数值之和)。值之和)。publicclassMyRunnableimplementsRunnableprivateFoofoo=newFoo();publicstaticvoidmain(Stringargs)MyRunnabler=newMyRunnable();Threadta=newThread(r,Thread-A);Threadtb=newThread(r,Thread-B);ta.start();tb.start();publicvoidrun()synchronized(this)for(inti=0;i0则成功,否则则成功,否则失败。失败。/修改数据修改数据Stringupdatesql=UPDATEstudentSETsname=李四李四WHERExh=1;/修改修改sqlintresult=st.executeUpdate(updatesql);/如果如果result0则成功,否则则成功,否则失败。失败。/查询数据查询数据Stringselectsql=SELECT*FROMstudent;/查询查询sqlResultSetrs=st.executeQuery(selectsql);ResultSet接口ResultSet接口用来暂时存放数据库查询接口用来暂时存放数据库查询操作所获得的结果,用来对结果集中的操作所获得的结果,用来对结果集中的数据进行访问数据进行访问 方法说明booleanabsolute(introw)将游标移动到结果集的某一行voidafterLast()将游标移动到结果集的末尾voidbeforeFirst()将游标移动到结果集的头部voiddeleteRow()删除结果集中的当前行voidinsertRow()在结果集中插入一行voidmoveToInsertRow()移动游标到新插入的行voidupdateRow()更新修改记录booleanfirst()将游标移动到结果集的第一行XXXgetXXX(intconlumnIndex)获取当前行某一列的值,返回值的类型为XXXvoidupdateXXX(intconlumnIndex,XXXx)更新当前行列号为conlumnIndex的值为xvoidupdateXXX(intconlumnName,XXXx)更新当前行列名为conlumnName的值为xStatementgetStatement()获取产生该结果集的Statement对象intgetType()获取结果集的类型booleaninAfterLast()判断游标是否指向结果集的末尾booleanisBeforeFirst()判断游标是否指向结果集的头部booleanisFirst()判断游标是否指向结果集的第一行booleanisLast()判断游标是否指向结果集的最后一行booleanlast()将游标移动到结果集的最后一行booleannext()将游标移动到结果集的后面一行booleanprevious()将游标移动到结果集的前面一行结果集从其使用的特点上可以分为四类,这四类结果集所具备的特点都是和结果集从其使用的特点上可以分为四类,这四类结果集所具备的特点都是和Statement语句的创建有关,语句的创建有关,因为结果集是通过因为结果集是通过Statement语句执行后产生的,所以可以说,结果集具备何种特点,完全决定于语句执行后产生的,所以可以说,结果集具备何种特点,完全决定于Statement。最基本的最基本的ResultSet之所以说是最基本的之所以说是最基本的ResultSet,是因为这个,是因为这个ResultSet起到的作用就是完成查询结果的存储功能,而且只起到的作用就是完成查询结果的存储功能,而且只能读取一次,不能够来回的滚动读取。这种结果集能读取一次,不能够来回的滚动读取。这种结果集Statement创建方式如下:创建方式如下: Statementst=conn.CreateStatement();ResultSetrs=Statement.excuteQuery(sqlStr);由于这种结果集不支持滚动的读取功能,所以如果获得这样一个结果集,只能使用它的由于这种结果集不支持滚动的读取功能,所以如果获得这样一个结果集,只能使用它的next()方法逐个读方法逐个读取数据。取数据。 可滚动的可滚动的ResultSet这个类型支持在结果集中前后滚动、滚动到第一行、绝对滚动到指定行以及相对移动到指定行。这种结果这个类型支持在结果集中前后滚动、滚动到第一行、绝对滚动到指定行以及相对移动到指定行。这种结果集集Statement创建方式如下:创建方式如下:Statementst=conn.createStatement(intresultSetType,intresultSetConcurrency);ResultSetrs=st.executeQuery(sqlStr);其中:其中:resultSetType是设置是设置ResultSet对象是否可滚动的。当取值为对象是否可滚动的。当取值为ResultSet.TYPE_FORWARD_ONLY表示表示只能向前滚动,取值为只能向前滚动,取值为ResultSet.TYPE_SCROLL_INSENSITIVE和和ResultSet.TYPE_SCROLL_SENSITIVE时表示能够实现任意的前后滚动、绝对和相对滚动,二者的区别在于对数据的最新修改是否敏时表示能够实现任意的前后滚动、绝对和相对滚动,二者的区别在于对数据的最新修改是否敏感,即结果集中数据是否反映数据库中数据的实时更新。感,即结果集中数据是否反映数据库中数据的实时更新。resultSetConcurency是设置是设置ResultSet对象是否能够修改的。当取值为对象是否能够修改的。当取值为 ResultSet.CONCUR_READ_ONLY表示为只读,取值为表示为只读,取值为ResultSet.CONCUR_UPDATABLE表示为可修改。表示为可修改。例如,如果希望得到的结果集是可滚动且只读的,只要把例如,如果希望得到的结果集是可滚动且只读的,只要把Statement如下赋值就行了。如下赋值就行了。Statementst=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);ResultSetrs=st.excuteQuery(sqlStr);可更新的可更新的ResultSet这样的这样的ResultSet对象可以完成对数据库中数据的修改,但是对象可以完成对数据库中数据的修改,但是ResultSet只是相当于数据库中的视图,所以并不是所有的只是相当于数据库中的视图,所以并不是所有的ResultSet只要设置了可更新就能够完成数据更新的,要符合数据库中的数据更新条件。这种结果集只要设置了可更新就能够完成数据更新的,要符合数据库中的数据更新条件。这种结果集Statement创建方式如下:创建方式如下:Statementst=createstatement(Result.TYPE_SCROLL_INSENSITIVE,Result.CONCUR_UPDATABLE);可保持的可保持的ResultSet正常情况下如果使用正常情况下如果使用Statement执行完一个查询,又去执行另一个查询时,此时第一个查询的结果集就会被关闭,也就是说,所有执行完一个查询,又去执行另一个查询时,此时第一个查询的结果集就会被关闭,也就是说,所有的的Statement的查询对应的结果集是一个,如果调用的查询对应的结果集是一个,如果调用Connection的的commit()方法也会关闭结果集。可保持性就是指当方法也会关闭结果集。可保持性就是指当ResultSet的结果被提交时,是被关闭还是不被关闭。的结果被提交时,是被关闭还是不被关闭。JDBC2.0和和1.0提供的都是提交后提供的都是提交后ResultSet就会被关闭。不过在就会被关闭。不过在JDBC3.0中可以设置中可以设置ResultSet是否关闭。要完成这样的是否关闭。要完成这样的ResultSet的对象的创建,要使用的的对象的创建,要使用的Statement的创建要具有三个参数,这种结果集的创建要具有三个参数,这种结果集Statement创建方式如下:创建方式如下:Statementst=createStatement(intresultsetscrollable,intresultsetupdateable,intresultsetSetHoldability);ResultSetrs=st.excuteQuery(sqlStr);前两个参数的含义与前面相同,这里只介绍第三个参数。前两个参数的含义与前面相同,这里只介绍第三个参数。 resultSetHoldability表示在结果集提交后结果集是否打开,当取值为表示在结果集提交后结果集是否打开,当取值为 ResultSet.HOLD_CURSORS_OVER_COMMIT表示修改提交时,表示修改提交时,不关闭不关闭ResultSet,取值为,取值为 ResultSet.CLOSE_CURSORS_AT_COMMIT表示修改提交时表示修改提交时ResultSet关闭。关闭。利用利用ResultSet接口可以实现数据库的插入、删除、修改和查询操作。查询操作同接口可以实现数据库的插入、删除、修改和查询操作。查询操作同Statement接口。下面主要介绍更新操作。接口。下面主要介绍更新操作。关键代码如下:关键代码如下:Statementst=conn.CreateStatement(ResultSet.TYPE_SCORLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);Stringselectsql=SELECT*FROMstudent;/查询查询sqlResultSetrs=st.executeQuery(selectsql);/插入数据插入数据rs.moveToInsertRow();/插入数据插入数据rs.updateString(xh,010103);rs.updateString(sname,王五王五);.rs.insertRow();/将插入数据保存到数据库将插入数据保存到数据库rs.last();/移动光标到新增行移动光标到新增行/删除数据删除数据rs.last();/移动光标到新增行移动光标到新增行rs.deleteRow();/修改数据修改数据rs.last();rs.updateString(xh,010103);rs.updateString(sname,王五王五);.rs.updateRow();/将修改数据保存到数据库将修改数据保存到数据库rs.last();/移动光标到新增行移动光标到新增行PreparedStatement接口在在JDBC中有中有Statement、PreparedStatement和和CallableStatement三种三种Statement对象。对象。Statement对象用于执行不带参数的简单对象用于执行不带参数的简单SQL语句,语句,PreparedStatement继承了继承了Statement,用于处理需要被多次执行的,用于处理需要被多次执行的SQL语句,语句,可以带参数,可以带参数,CallableStatement继承了继承了PreparedStatement,用于执行对数据,用于执行对数据库的存储过程的调用。库的存储过程的调用。实际应用中,实际应用中,PreparedStatement与与Statement是有区别的。是有区别的。PreparedStatement不仅包含了不仅包含了SQL语句,而且大多数情况下这个语句已经被预语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需编译过,因而当其执行时,只需DBMS运行运行SQL语句,而不必先编译,因此会大语句,而不必先编译,因此会大大降低运行时间,加快访问数据库的速度。大降低运行时间,加快访问数据库的速度。作为作为 Statement的子类,的子类, PreparedStatement继承了继承了 Statement的所有方法,的所有方法,由于由于PreparedStatement接口执行带参数的接口执行带参数的sql语句,因此使用语句,因此使用setXXX(参数的(参数的序号,参数的值)方法来完成,其中序号,参数的值)方法来完成,其中 XXX是与该参数相应的类型。是与该参数相应的类型。利用利用PreparedStatement接口可以实现数据库的插入、删除、修改和查询操作。接口可以实现数据库的插入、删除、修改和查询操作。关键代码如下:关键代码如下:/插入数据插入数据Stringinsertsql=INSERTINTOstudent(xh,sname,ssex)VALUES(?,?,?);/插入插入sqlPreparedStatementpstmt=con.preparedStatement(insertsql);pstmt.setString(1,010104);pstmt.setString(2,朱克朱克);pstmt.setString(3,男男);pstmt.executeUpdate();PreparedStatement接口/删除数据删除数据Stringdeletesql=DELETEFROMstudentWHERExh=?;/删除删除sqlPreparedStatementpstmt=con.preparedStatement(deletesql);pstmt.setString(1,010104);intresult=pstmt.executeUpdate();/如果如果result0则成功,否则失败。则成功,否则失败。/修改数据修改数据Stringupdatesql=UPDATEstudentSETsname=?WHERExh=?;/修改修改sqlPreparedStatementpstmt=con.preparedStatement(updatesql);pstmt.setString(1,朱克新朱克新);pstmt.setString(2,010104);intresult=pstmt.executeUpdate();/如果如果result0则成功,否则失败。则成功,否则失败。/查询数据查询数据Stringselectsql=SELECT*FROMstudentWHERExh=?;/查询查询sqlPreparedStatementpstmt=con.preparedStatement(selectsql);pstmt.setString(1,010104);ResultSetrs=pstmt.executeQuery();11.1.2JDBC访问数据库的一般步骤调用调用Class.forName()方法加载驱动程序。方法加载驱动程序。调用调用DriverManager对象的对象的getConnection()方法,方法,获得一个获得一个Connection对象。对象。创建一个创建一个Statement对象,准备一个对象,准备一个SQL语句,这语句,这个个SQL语句可以是语句可以是Statement对象(立即执行的语句)、对象(立即执行的语句)、PreparedStatement语句(预编译的语句)或语句(预编译的语句)或CallableStatement对象(存储过程调用的语句)。对象(存储过程调用的语句)。调用调用executeQuery()等方法执行等方法执行SQL语句,并将结语句,并将结果保存在果保存在ResultSet对象;或者调用对象;或者调用executeUpdate()等方法执行等方法执行SQL语句,不返回语句,不返回ResultSet对象的结果。对象的结果。对返回的对返回的ResultSet对象进行显示等相应的处理。对象进行显示等相应的处理。 importjava.sql.*;publicclassDatabaseDemopublicstaticvoidmain(Stringargs)StringstrDBDriver=sun.jdbc.odbc.JdbcOdbcDriver;StringstrDBUrl=jdbc:odbc:user;Connectionconn=null;Statementstmt=null;ResultSetrs=null;Stringss;tryClass.forName(strDBDriver);catch(java.lang.ClassNotFoundExceptione)System.out.println(classforname()创建失败!创建失败!);tryconn=DriverManager.getConnection(strDBUrl,);/创建数据库连接对象创建数据库连接对象/游标可以移动,且只读方式建立游标可以移动,且只读方式建立stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);ss=insertintouser(id,password)values(0000,0000);stmt.execute(ss);rs=stmt.executeQuery(select*fromuser);while(rs.next()System.out.println(rs.getString(1);System.out.println(rs.getString(2);ss=updateusersetpassword=000000whereid=0000;stmt.execute(ss);rs=stmt.executeQuery(select*fromuser);while(rs.next()System.out.println(rs.getString(1);System.out.println(rs.getString(2);ss=deletefromuserwhereid=0000;stmt.execute(ss);rs=stmt.executeQuery(select*fromuser);while(rs.next()System.out.println(rs.getString(1);System.out.println(rs.getString(2);catch(SQLExceptionex)System.out.println(SQL失败!失败!);trystmt.close();catch(SQLExceptione)System.out.println(stmt关闭失败!关闭失败!);tryconn.close();catch(SQLExceptione)System.out.println(conn关闭失败!关闭失败!);11.1.3Java连接数据库的方法Java连接数据库主要有两种方法,一是连接数据库主要有两种方法,一是用用JDBC-ODBC桥来连接,二是用相关桥来连接,二是用相关厂商提供的相应驱动程序来连接。厂商提供的相应驱动程序来连接。 JDBC-ODBC桥方式JDBC-ODBC桥接器是用桥接器是用JdbcOdbc.Class和和一个用于访问一个用于访问ODBC驱动程序的本地库实现的。驱动程序的本地库实现的。对于对于Windows平台,该本地库是一个动态连接平台,该本地库是一个动态连接库库DLL(JDBCODBC.DLL)。由于由于JDBC在设计上与在设计上与ODBC很接近。在内部,很接近。在内部,这个驱动程序把这个驱动程序把JDBC的方法映射到的方法映射到ODBC调调用上,这样,用上,这样,JDBC就可以和任何可用的就可以和任何可用的ODBC驱动程序进行交互了。这种桥接器的优驱动程序进行交互了。这种桥接器的优点是,它使点是,它使JDBC目前有能力访问几乎所有的目前有能力访问几乎所有的数据库。数据库。 使用使用JDBC-ODBC桥方式连接数据库的过程桥方式连接数据库的过程应用程序应用程序JDBCAPIJDBC-ODBC-ODBCAPIODBC层层数据源数据源连接数据库的具体操作方法连接数据库的具体操作方法首先打开控制面板的管理工具,打开数据源首先打开控制面板的管理工具,打开数据源(ODBC),在用户),在用户DSN里面添加数据源,与里面添加数据源,与要连接的数据库建立连接即可。要连接的数据库建立连接即可。关键代码关键代码Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);/加载加载JDBC-ODBC驱动驱动conn=DriverManager.getConnection(url);/连接数连接数据库据库 JDBCAPI方式这种实现方法是直接使用数据库厂商提供的用这种实现方法是直接使用数据库厂商提供的用专用的网络协议创建的驱动程序,通过它可以专用的网络协议创建的驱动程序,通过它可以直接将直接将JDBCAPI调用转换为直接网络调用。调用转换为直接网络调用。这种调用方式一般性能比较好,而且也是实际这种调用方式一般性能比较好,而且也是实际应用中最简单的方法,因为它不需要安装其他应用中最简单的方法,因为它不需要安装其他的库或中间件,几乎所有的数据库厂商都为他的库或中间件,几乎所有的数据库厂商都为他们的数据库提供了这种们的数据库提供了这种JDBC驱动程序。从网驱动程序。从网址址http:/industry.Java.sun.com/products/jdbc/drivers/可以看到所有有用的驱动程序的清可以看到所有有用的驱动程序的清单。单。 使用使用JDBCAPI方式连接数据库的过程方式连接数据库的过程应用程序应用程序JDBCAPI驱动程序驱动程序数据源数据源连接数据库的具体操作方法连接数据库的具体操作方法首先打开控制面板的管理工具,打开数据源首先打开控制面板的管理工具,打开数据源(ODBC),在系统),在系统DSN里面添加数据源,与里面添加数据源,与要连接的数据库建立连接即可。要连接的数据库建立连接即可。利用此种方法连接数据库首先要安装相应数据利用此种方法连接数据库首先要安装相应数据库的库的JDBC的驱动程序,此程序可从网上下载,的驱动程序,此程序可从网上下载,地址参见地址参见11.3.5。常用数据库常用数据库JDBCAPI编程代码见书。编程代码见书。Java程序设计基础与实践 第12章网络编程TCP和和UDP的概念的概念基于基于TCP协议的网络编程方法协议的网络编程方法基于基于UDP协议的网络编程方法协议的网络编程方法InetAddress类和类和URL类类12.1.1TCP和和UDPTCPTCP的全称为的全称为TransmissionControlProtocol,称为,称为网络传输控制协议,主要负责数据的分组和重组,它网络传输控制协议,主要负责数据的分组和重组,它与与IP协议组合,称为协议组合,称为TCP/IP。UDPUDP的全称为的全称为UserDatagramProtocol,称为用户数,称为用户数据报协议,和据报协议,和TCP不同,不同,UDP是一种非持续连接的通是一种非持续连接的通信协议,它不能保证数据能够正确抵达目标,而且多信协议,它不能保证数据能够正确抵达目标,而且多个数据包抵达目标的顺序可能与发送时的顺序不同。个数据包抵达目标的顺序可能与发送时的顺序不同。12.1.2InetAddress类类IP地址是每个计算机在网络中的唯一标识,要想进行地址是每个计算机在网络中的唯一标识,要想进行网路通信,必须获得正确的网路通信,必须获得正确的IP地址。地址。Java提供了提供了IP地地址的封装类址的封装类InetAddress。方法方法说明说明getByName(Strings)获取指定主机的获取指定主机的IP地址地址getLocalhost()返回本地主机的返回本地主机的InetAddress对象对象getHostName()getHostName()获取此主机名获取此主机名getHostAddress()getHostAddress()获取此主机获取此主机IP地址地址isReachable(int isReachable(int timeout)timeout)在在timeout指定的毫秒时间内,测试指定的毫秒时间内,测试IP地址是地址是否可达否可达表表12.1InetAddress类常用方法类常用方法例如:获取域名为例如:获取域名为“www.sina.com.cn”的网络的网络IP地址等信息。地址等信息。importjava.net.*;publicclassTestpublicstaticvoidmain(Stringargs)try /try /使用使用InetAddress类要进行异常处理类要进行异常处理InetAddressaddress=InetAddress.getByName(www.sina.com.cn);StringdomainName=address.getHostName();StringipName=address.getHostAddress();InetAddressmine=address.getLocalHost();System.out.println(domainName);System.out.println(ipName);System.out.println(mine.toString();catch(UnknownHostExceptione)e.printStackTrace();12.1.3基于基于TCP协议的网络编程协议的网络编程创建服务器端套接字创建服务器端套接字服务器端套接字是服务器端套接字是ServerSocket类的实例对象,用于类的实例对象,用于实现服务器程序,实现服务器程序,ServerSocket类监视指定的端口,类监视指定的端口,并建立客户端到服务器端套接字的连接,也就是负责并建立客户端到服务器端套接字的连接,也就是负责客户端的呼叫任务。客户端的呼叫任务。例如:例如:tryServerSocketss=newServerSocket(1880);catch(IOExceptione)创建客户端套接字创建客户端套接字客户端端套接字是客户端端套接字是Socket类的实例对象,用于实现客类的实例对象,用于实现客户端程序。户端程序。服务器端接受客户端请求服务器端接受客户端请求在服务器端利用其在服务器端利用其accept()方法接收客户端的套接字方法接收客户端的套接字连接请求。连接请求。例如,上面创建的服务器端套接字例如,上面创建的服务器端套接字ss接受客户端请求,接受客户端请求,代码如下:代码如下:trymysocket=ss.accept();catch(IOExceptione)客户端发送和接收服务器客户端发送和接收服务器Socket类提供了类提供了getInputStream()方法和方法和getOutStream()方法来接收和发送数据。方法来接收和发送数据。例如:一个简单的聊天室例如:一个简单的聊天室客户端程序客户端程序:importjava.io.*;importjava.net.*;public class Student /public class Student /学生类学生类publicstaticvoidmain(Stringargs)trySocketsocket=newSocket(127.0.0.1,4700); / /向本机的向本机的4700端口发出客户请求端口发出客户请求BufferedReadersin=newBufferedReader(newInputStreamReader(System.in); / /由系统标准输入设备构造由系统标准输入设备构造BufferedReader对象对象PrintWriteros=newPrintWriter(socket.getOutputStream(); / /由由Socket对象得到输出流,并构造对象得到输出流,并构造PrintWriter对象对象BufferedReaderis=newBufferedReader(newInputStreamReader(socket.getInputStream(); / /由由Socket对象得到输入流,并构造相应的对象得到输入流,并构造相应的BufferedReader对象对象Stringreadline; readline=sin.readLine(); / readline=sin.readLine(); /从系统标准输入读入一字符串从系统标准输入读入一字符串while(!readline.equals(bye) / /若从标准输入读入的字符串为若从标准输入读入的字符串为 bye则停止循环则停止循环os.println(readline); / /将从系统标准输入读入的字符串输出到将从系统标准输入读入的字符串输出到Serveros.flush(); / /刷新输出流,使刷新输出流,使Server马上收到该字符串马上收到该字符串 System.out.println(System.out.println(学生学生:+readline); / /在系统标准输出上打印读入的字符串在系统标准输出上打印读入的字符串 System.out.println(System.out.println(老师老师:+is.readLine(); / /从从Server读入一字符串,并打印到标准输出上读入一字符串,并打印到标准输出上 readline=sin.readLine(); /readline=sin.readLine(); /从系统标准输入读入一字符串从系统标准输入读入一字符串 / /继续循环继续循环 os.close(); /os.close(); /关闭关闭Socket输出流输出流 is.close(); /is.close(); /关闭关闭Socket输入流输入流 socket.close(); /socket.close(); /关闭关闭Socketcatch(Exceptione) System.out.println(Error+e); / System.out.println(Error+e); /出错,则打印出错信息出错,则打印出错信息服务器端程序服务器端程序:importjava.io.*;importjava.net.*;public class Teacher /public class Teacher /老师类老师类publicstaticvoidmain(Stringargs)tryServerSocketserver=null;tryserver=newServerSocket(4700); / /创建一个创建一个ServerSocket在端口在端口4700监听客户请求监听客户请求catch(Exceptione)System.out.println(cannotlistento:+e); / /出错,打印出错信息出错,打印出错信息Socketsocket=null;trysocket=server.accept(); / /使用使用accept()阻塞等待客户请求,有客户阻塞等待客户请求,有客户 /请求到来则产生一个请求到来则产生一个Socket对象,并继续执行对象,并继续执行catch(Exceptione)System.out.println(Error.+e); / /出错,打印出错信息出错,打印出错信息Stringline;BufferedReaderis=newBufferedReader(newInputStreamReader(socket.getInputStream(); / /由由Socket对象得到输入流,并构造相应的对象得到输入流,并构造相应的BufferedReader对象对象PrintWriteros=newPrintWriter(socket.getOutputStream(); / /由由Socket对象得到输出流,并构造对象得到输出流,并构造PrintWriter对象对象BufferedReadersin=newBufferedReader(newInputStreamReader(System.in); / /由系统标准输入设备构造由系统标准输入设备构造BufferedReader对象对象 System.out.println(System.out.println(学生学生:+is.readLine(); / /在标准输出上打印从客户端读入的字符串在标准输出上打印从客户端读入的字符串line=sin.readLine(); / /从标准输入读入一字符串从标准输入读入一字符串while(!line.equals(bye) / /如果该字符串为如果该字符串为 bye,则停止循环,则停止循环os.println(line); / /向客户端输出该字符串向客户端输出该字符串os.flush(); / /刷新输出流,使刷新输出流,使Client马上收到该字符串马上收到该字符串 System.out.println(System.out.println(老师老师:+line); / /在系统标准输出上打印读入的字符串在系统标准输出上打印读入的字符串 System.out.println(System.out.println(学生学生:+is.readLine(); / /从从Client读入一字符串,并打印到标准输出上读入一字符串,并打印到标准输出上line=sin.readLine(); / /从系统标准输入读入一字符串从系统标准输入读入一字符串 / /继续循环继续循环 os.close(); /os.close(); /关闭关闭Socket输出流输出流 is.close(); /is.close(); /关闭关闭Socket输入流输入流 socket.close(); /socket.close(); /关闭关闭Socket server.close(); / server.close(); /关闭关闭ServerSocketcatch(Exceptione)System.out.println(Error:+e); / /出错,打印出错信息出错,打印出错信息多客户的多客户的Client/Server程序设计程序设计 为了实现在服务器方给多个客户提供服务的功能,需要为了实现在服务器方给多个客户提供服务的功能,需要对上面的程序进行改造,利用多线程实现多客户机制。对上面的程序进行改造,利用多线程实现多客户机制。例如:多线程实现例如:多线程实现Socket套接字的示例。套接字的示例。客户端客户端端程序端程序:importjava.net.*;importjava.io.*;publicclassStudent1publicstaticvoidmain(Stringargs)throwsExceptionSocketserver=newSocket(localhost,4700); / /向本机的向本机的4700端口发出客户请求端口发出客户请求BufferedReaderin=newBufferedReader(newInputStreamReader(server.getInputStream(); / /由由Socket对象得到输入流,并构造相应的对象得到输入流,并构造相应的BufferedReader对象对象PrintWriterout=newPrintWriter(server.getOutputStream(); / /由由Socket对象得到输出流,并构造对象得到输出流,并构造PrintWriter对象对象BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in); / /由系统标准输入设备构造由系统标准输入设备构造BufferedReader对象对象while(true)Stringstr=br.readLine(); / /从系统标准输入读入一字符串从系统标准输入读入一字符串out.println(str); / /将从系统标准输入读入的字符串输出到将从系统标准输入读入的字符串输出到Serverout.flush(); / /刷新输出流,使刷新输出流,使Server马上收到该字符串马上收到该字符串if(str.equals(bye) / /若从标准输入读入的字符串为若从标准输入读入的字符串为 bye则停止循环则停止循环break;System.out.println(in.readLine(); / /从从Server读入一字符串,并打印到标准输出上读入一字符串,并打印到标准输出上server.close(); / /关闭关闭Socket服务器端程序服务器端程序:importjava.net.*;importjava.io.*;public class Teacher extends Thread /public class Teacher extends Thread /多线程多线程privateSocketsocket;publicTeacher(Socketsocket)this.socket=socket; public void run() / public void run() /线程主体线程主体tryBufferedReaderin=newBufferedReader(newInputStreamReader(socket.getInputStream(); / /由由Socket对象得到输入流,并构造相应的对象得到输入流,并构造相应的BufferedReader对象对象PrintWriterout=newPrintWriter(socket.getOutputStream(); / /由由Socket对象得到输出流,并构造对象得到输出流,并构造PrintWriter对象对象while(true)Stringstr=in.readLine(); System.out.println( System.out.println(学生说:学生说:+str); / /在标准输出上打印从客户端读入的字符串在标准输出上打印从客户端读入的字符串 out.println(out.println(学生学生:+str); / /向客户端输出该字符串向客户端输出该字符串out.flush(); / /刷新输出流,使刷新输出流,使Client马上收到该字符串马上收到该字符串if(str.equals(bye)break;catch(IOExceptione)System.out.println(e.getMessage(); / /出错,打印出错信息出错,打印出错信息publicstaticvoidmain(Stringargs)throwsIOExceptionServerSocketserver=newServerSocket(4700); / /创建一个创建一个ServerSocket在端口在端口4700监听客户请求监听客户请求while(true)Sockets=server.accept(); / /使用使用accept()阻塞等待客户请求,有客户请求到来则产生一个阻塞等待客户请求,有客户请求到来则产生一个Socket对象,并继续执行对象,并继续执行newTeacher(s).start();12.1.4基于基于UDP协议的网络编程协议的网络编程DatagramPacket类类DatagramPacket类是类是UDP所传递的数据包,即打包所传递的数据包,即打包数据。数据。DatagramSocket类类DatagramSocket类是用于发送和接收数据的数据包套类是用于发送和接收数据的数据包套接字。接字。例如:例如:DatagramSocketreceivedata=newDatagramSocket(7312);bytedata=newbyte100;intlength=60;DatagramPacketdata_pack=newDatagramPacket(data,length);receivedata.receive(data_pack);同学同学A:importjava.net.*;importjava.io.*;classStudentAextendsThread / /实现多线程实现多线程DatagramPacketpack=null;bytedata=newbyte8192;publicvoidrun() / /数据接收数据接收DatagramSocketrecieve_data=null;tryrecieve_data=newDatagramSocket(666); / /接收端口接收端口666pack=newDatagramPacket(data,data.length); catch(Exceptione)while(true)if(recieve_data=null)break;elsetryrecieve_data.receive(pack); / /接收数据报接收数据报packintlength=pack.getLength();Stringmessage=newString(pack.getData(),0,length);/将数据报转换为字符串将数据报转换为字符串 System.out.println(System.out.println(接收到接收到StudentB的数据:的数据:+message);/将字符串通过将字符串通过标准输出打印在控制台上标准输出打印在控制台上catch(Exceptione)publicstaticvoidmain(Stringargs)throwsExceptionStudentAs=newStudentA();s.start();BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in);/由系统标准输入设备构造由系统标准输入设备构造BufferedReader对象对象while(true)Stringstr=br.readLine(); / /从系统标准输入读入一字符串从系统标准输入读入一字符串bytebuffer=str.getBytes();InetAddressaddress=InetAddress.getByName(localhost);DatagramPacketdata_pack=newDatagramPacket(buffer,buffer.length,address,888); /将数据发送到本机将数据发送到本机888端口端口DatagramSocketsent_data=newDatagramSocket();sent_data.send(data_pack); / /发送数据报发送数据报同学同学B:importjava.net.*;importjava.io.*;classStudentBextendsThread / /实现多线程实现多线程DatagramPacketpack=null;bytedata=newbyte8192;publicvoidrun() / /数据接收数据接收DatagramSocketrecieve_data=null;tryrecieve_data=newDatagramSocket(888); / /接收端口接收端口888pack=newDatagramPacket(data,data.length);catch(Exceptione)while(true)if(recieve_data=null)break;elsetryrecieve_data.receive(pack); / /接收数据报接收数据报packintlength=pack.getLength();Stringmessage=newString(pack.getData(),0,length);/将数据报转换为字符串将数据报转换为字符串 System.out.println(System.out.println(接收到接收到StudentA的数据:的数据:+message); / /将字符串通过标准输出打印在控制台上将字符串通过标准输出打印在控制台上catch(Exceptione)publicstaticvoidmain(Stringargs)throwsExceptionStudentBs=newStudentB();s.start();BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in);/由系统标准输入设备构造由系统标准输入设备构造BufferedReader对象对象while(true)Stringstr=br.readLine();/从系统标准输入读入一字符串从系统标准输入读入一字符串bytebuffer=str.getBytes();InetAddressaddress=InetAddress.getByName(localhost);DatagramPacketdata_pack=newDatagramPacket(buffer,buffer.length,address,666); / /将数据发送到本机将数据发送到本机666端口端口DatagramSocketsent_data=newDatagramSocket();sent_data.send(data_pack); / /发送数据报发送数据报12.1.5URL类类URL代表一个统一资源定位符,它是指向互联网代表一个统一资源定位符,它是指向互联网“资资源源”的指针。的指针。简单的可以把简单的可以把URL理解为包含协议、主机名、端口、理解为包含协议、主机名、端口、路径、查询字符串和参数等对象,每一段可以独立设路径、查询字符串和参数等对象,每一段可以独立设置。置。例如:使用例如:使用URL下载网页的示例。下载网页的示例。importjava.net.*;importjava.io.*;classTestpublicstaticvoidmain(Stringargs)throwsIOExceptionInputStreamin=null;tryURLu=newURL(http:/www.google.cn/);in=u.openStream();for(intc=in.read();c!=-1;c=in.read()System.out.write(c);catch(MalformedURLExceptionex)ex.printStackTrace();finallyif(in!=null)in.close();
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号