Java编程基础教程

    Java编程基础教程

    前言

    在最受欢迎的程序设计语言排行榜上,Java语言已经连续数年位列榜首。“Write once, Run anywhere,(一次编写,到处可行)”,这是一种很有效率的编程方式。跨平台、完全面向对象、既适于单机编程也适合于Internet编程等特点,给Java语言注入了强大的生命力。而Java语言也取得了举世瞩目、全球公认的地位。

    如今的时代,电子设备嵌入Java技术,Java智能卡海量发行,PC中广泛应用Java技术,电信运营商支持Java技术,Java开发人员数量也日增月长。另外,Java开发者锐意创新,将Java技术应用到各种领域,使得Java技术已经成为世界上最卓越的企业应用和移动应用开发平台之一。历史上从没有过像Java平台这样能够如此广泛地应用,许多公司和软件人员大量使用Java技术。

    亲爱的读者,如果你是在校生,正在上Java程序设计这门课程,请你珍惜校园的时光,珍惜学习的机会,发挥你的聪明才智吧,Java已经是无处不在,你的努力也不会徒然。如果你是一个自学者,那跟随本书二十四讲的引领,循序渐进,你一定能从入门到进阶,假如你有困惑之处,欢迎给编者发邮件讨论。如果您是一位老师,为您的学生选择课本,您此时手中的这一本应是一个不错的选择,教、学、做几个环节,一本书通达。

    

    Java语言入门篇—主要为零起点的读者准备。对于有C或C++语言基础的读者,该篇简单学习即可。

    面向对象篇—至关重要的理论篇,为所有学习Java语言的读者准备,学习该篇时要缓进而踏实,精学多悟,可辅以上机实训加强理论理解。

    数据流应用篇—不可或缺的应用篇,为所有学习Java语言的读者准备,文件的输入/输出是语言基本的功能,该篇的学习策略应以上机实训为主,从验证到设计。

    Java GUI编程篇—重要应用篇,通过该篇的学习,读者可设计出视窗风格的应用程序。本篇的学习策略是实践、再实践,从小的示例到较大的项目设计。

    高级应用篇—进阶选学篇,全篇内容可根据课时情况,按务实原则选学选讲。 各篇分讲合成:

    每篇由3~7讲组成,同一篇中的各讲循序渐进,由浅入深,由入门到提高。面向对象篇和Java GUI编程篇中的最后一讲都可作为选学或自学的内容。高级应用篇中的第二十讲建议选学,其后的各讲可跳选。

    一讲一主题,每讲可对应2学时左右。 集成实践环节:

    上机实训和指导,共安排了二十四个实训,一讲对应一个实训,实训部分可根据课时选做,建议读者在课时外补充完成所有实训。若采用“教、学、做一体化”的教学方式,可将讲训联合,教和学、学和做便有机融成一体。

    课程设计任务和指导,安排了一个“写字留痕”日记本的设计课题,可作为1~2周的设计实践。课题涉及知识基本在前四篇中,扩展的一小部分新知识在“指导”环节进行了说明和演示。指导环节还补充了将Java应用程序包装成可执行的Jar文件的简捷方法,该方法可在学习应用篇的过程中提前穿插学习。

    

   

一、Java语言快速入门 

内容: Java的起源和发展历程 Java语言的工作原理及特点 Java开发环境的建立 第一个程序的编译和运行 一、Java的起源和发展历程

    作为一名Java语言的学习者,对Java的起源和发展有个概略认识应是必要的。

1. Java的起源 。Java起源于20世纪90年代初Sun公司的一个叫Green的项目,该项目的目标是开发嵌入家用电器的分布式软件系统,使电器更加智能化。项目小组成员皆为C++的高手,便采用C++进行系统开发,但在开发过程中发现了很多问题,如C++语言过于复杂、安全性差等。于是项目小组只好另辟蹊径,在“简单的、可靠的、紧凑的并易于移植的”的框架内开发了一个小型的计算机语言,用于编写消费者的电子产品中的程序,当时这款语言命名为Oak,橡树的意思。至于这Oak怎么变成了Java......

  

    二、Java语言的工作原理及特点

1. Java是一门怎样的语言。 Sun公司出品了Java,它对Java语言有专门的描述:“Java is a simple, object-oriented, distributed, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, and dynamic language.”

    它告诉你Java是简单的、面向对象的、分布式的、解释的、健壮的、安全的、结构中立的、轻便的、高性能的、多线程的动态语言。所有这些形容词恰恰指明了Java语言的特点和工作原理。

    2. 跨平台特性

    关于Java程序,有一句口号式的经典描述—“Write once, Run anywhere”,其中文意思是“一次编写,到处运行”。这指的正是Java语言跨平台的特性。

    Java源代码被编译成一种结构中立的中间文件格式,在机器上能直接执行这种中间代码,不管机器是什么型号的,操作系统是哪种。但有一个必要的前提:那台运行Java程序的机器上需要预先安装Java运行系统。Java运行系统又称为Java虚拟机(简称JVM),它可以从java.sun.com网站免费下载,不同的操作系统需要安装对应的JVM版本。而Java的跨平台特性即通过JVM实现。

    

    3. 完全面向对象

    Java语言是一门面向对象的语言,它比C++等语言新,一张白纸上可以画最美好的图画,20世纪90年代初它就是这样一张白纸,以James Gosling为首的Green项目团队给它画的那幅画是完全面向对象,一切皆为对象。

    什么是对象呢?对象是可存储数据的变量和可提供操作的方法的集合。对象的核心就是两项:变量和方法。每个对象在内存中都占据独立的空间,每个对象都拥有类型,对象从类型创建而来。

    4. 多线程

    Java中提供了专门的类,可方便地用于多线程编程。

    多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。

    多线程的程序可同时执行多个任务,多线程程序具有更好的交互性、实时性。 5. 内存垃圾自动回收

    在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其他对象;而在Java中,JVM的一个系统级线程可以监督对象,它可以发现对象何时不再被使用,原先分配给该对象的内存即成为了垃圾,JVM系统线程会释放该内存块,对象即被销毁,内存垃圾就被自动回收。

    事实上,除了释放没用的对象,Java垃圾收集也可以清除内存碎片。JVM将经过碎片整理后的内存分配给新的对象。

    6. 简洁有效

    Java语言的语法大多基于C++,但Java更加严谨、简洁。这体现在如下方面: Java去除了C++中一些难以理解、容易混淆的因素,如头文件、指针、结构体等;避免了赋值语句与逻辑运算语句的混淆;避免了隐藏变量带来的困惑,如“if(a = 3)?;”,在C++中是没问题的,而在Java中是错误的;取消了多重继承这一复杂的继承机制。

    Java提供了对内存的自动管理:内存分配、内存释放。 Java提供了丰富的类库,有利于软件开发的高效和标准化。 7. 健壮且安全

    Java程序首先要通过编译的环节,而Java有着最严格的“编译器”,可在编译阶段尽早发现错误,只有纠错完毕才能编译成功,生成字节码文件。这是健壮性的一个保证。字节码文件通过JVM解释执行,类装入器负责装入运行一个程序需要的所有类,确定整个可执行程序的内存布局。字节码校验器对装入的代码进行检查。校验器可发现操作数栈溢出、非法数据类型转换等多种错误。解释执行的机制是又一个健壮保证。

    另外解释器的沙盒运行模式,Java网络程序被限制访问本地资源,这些保障了系统的安全性。

    三、Java开发环境的建立

    一台计算机上安装了JVM,该台机器就可运行Java程序;而要开发Java程序,计算机上仅仅有JVM还是不够的,需要建立Java开发环境才行。

    选择什么样的版本,是J2SE还是J2EE,或者是J2ME?这要看从事哪方面的Java开发应用。本书使用J2SE来讨论Java程序设计,因此需要下载和安装JavaSE开发包。

    1. JavaSE的组成

    JavaSE是一个包含Java开发环境和运行环境的套件,该套件由如下三项集成: Java Development kit(JDK),Java程序开发环境。

    Java Runtime Environment(JRE),Java 应用程序运行环境。 Java Plug-in,使Java Applet可在网页中运行的插件。

2. 建立JavaSE开发环境 。有关Java平台方面的软件都是免费开放的,可直接从Sun公司的Java技术支持网站(http://java.sun.com)上下载,网站上提供了众多不同标准和版本的Java语言平台。下载JavaSE开发包,直接输入地址http://java.sun.com/javase/downloads/index.jsp亦可。

    安装过程是简捷的,双击下载文件,选择安装目录(如C:\java\jdk1.6.0_04),按步操作即可。

    3. 设置环境变量

    安装完毕需要设置path和classpath两个环境变量,这对于以后程序能否编译,编译成功的程序能否运行都是很关键的一个环节。

    要设置环境变量,先要弹出如图1-3所示的属性窗口。这在Windows XP下可通过右击桌面中的“我的电脑”,在弹出的快捷菜单中选择“属性”命令即可;在Windows Vista下可通过“开始”菜单,右击“计算机”,在弹出的快捷菜单中选择“属性”命令,再单击左栏任务下的最后一项“高级系统设置”即弹出属性窗口。然后在属性窗口的“高级”选项卡下,单击“环境变量”按钮就会弹出“环境变量”设置窗口。path 用于设置Java编译、解释等工具的路径,这些工具文件在Java安装目录下的bin目录中。path的设置如图1-3所示。

    classpath用于设置应用程序类路径和扩展的应用程序类路径,通常需要指定两项Java安装目录下的lib目录和当前运行的class所在目录(用“·”指定)。classpath的设置如图1-4所示。

    4. bin目录下几个Java实用工具

    在bin目录下有若干Java的工具软件,常用的几个工具软件见表1-3。 表1-3 几个Java实用工具

    四、第一个Java程序的编译和运行 Java程序有两种常用的应用形式: 应用程序(Application)嵌入在HTML文件中的小程序(Applet)

    本书大部分篇幅讨论的是Java应用程序的设计,Java应用程序是可以独立运行的程序,而Java Applet则不可独立运行,需要嵌入到网页文件中运行,Applet可使网页产生生动活泼的画面,使网页由静态转变为动态。

    1. 第一个Java程序

    下面就给出第一个Java程序,我们可以在记事本等编辑软件中编辑Java程序,编辑完毕保存成文本文件,但扩展名不能是记事本默认的“.txt”,而应是“.java”。如果给这个程序起名为Hello,那这个程序的全名则是Hello.java。

    2. 编译和运行

    一个Java程序编写完后先要编译才能解释运行。编译无错将生成结构中立的字节码文件。由表1-3得知javac.exe即为Java编译器,所以可以用命令javac Hello.java对以上的Hello.java文件进行编译,编译后生成字节码文件名为程序首行class后的类名,扩展名为“.class”,本例生成的字节码文件为HelloWorld.class。

    之后用Java解释器java.exe对字节码文件解释即得结果。编译和运行过程如图1-6所示。

    3. JCreator集成软件简介

    JCreator是一款适合于Java语言编程初学者的集成软件,对JCreator进行基本设置后,即可直接完成程序编写、编译和运行Java程序的全过程。JCreator操作界面简洁,提供的基本功能也较丰富,有代码缩进、自动类库方法提示、关键字高亮显示、无限撤销等。J2SE+JCreator是Java初学者较好的选择,这可让学习者把更多精力放在Java语言本身,而非工具的使用上。JCreator操作界面如图1-7所示。

    通常应先安装J2SE,后安装JCreator,这样JCreator会自动辨识J2SE文件夹,“JDK配置文件”选项下会自动配置classpath。否则需要通过“配置”→“选项”弹出“选项”对话框,后对“JDK配置文件”一栏进行设置。

    如图1-8所示的“选项”对话框中,JDK配置文件已设定。假如尚未设定,或单击右侧的“删除”按钮将已有的设定内容删除,则需要重新设定。这可通过右上方的“新建”按钮完成。

    当单击“新建”按钮后,会弹出如图1-9所示的“选择路径”对话框,选择已安装在机器里的JDK目录,后单击下方的“确定”按钮,即弹出如图1-10所示的“JDK配置文件”对话框,利用其上的“添加”按钮可继续加入扩展的类路径。JCreator中有些快捷键是十分好用的,它们可方便程序的编辑,成批语句行移动位置,可缩进程序中的语句,这样既符合了标准的书写格式,又让程序清晰可读;可以给语句行加上注释,在调试程序的时候十分好用。程序出错了,错在哪里需要排查才知,注释就可起到排查时的辅助作用。

   

    4. Java程序的基本结构 下面给出第二个Java程序。

    

​
[HelloDate.java]

    import java.util.*; 
     public class HelloDate{

     public static void main(String[] args){
     System.out.print("Hello, It is"); 
      System.out.println(new Date()); 
     } 
 }

​

    程序的运行结果是:

    1. Hello,It is Tue May 05 20:05:35 CST 2009

    通过阅读以上两个程序,我们对Java程序建立了初步的认识。这个程序命名为HelloDate.java是随意的吗?否!那第一个程序怎么没命名成HelloWorld.java呢?原因就在“public”上。请记住“public class??”这样定义的类,必须将class后的那个类名作为文件名。

    Java程序的基本组成有如下两部分: 导入包

    1. import 包名;

    类定义

    1. class 类名{ 2. 类体 3. }

    下面作进一步的说明:

    1)可执行的Java程序,必有一个类中含main方法。

    2)main方法有固定格式,如public static void main(String[] args),其中只有参数名args是可自定的。main前的每个修饰词都不可缺,顺序亦不可错。

    3)方法和类都需用成对的花括号界定。

    4)Java程序块中语法类同C++,每条语句用分号结束。

    5)Java程序对大小写敏感,class后的类名由大写字母开头,变量名、对象名由小写字母开头,常用修饰词与方法名以小写字母开头。

    本讲扼要介绍了Java语言的发展历程和Java程序工作原理。Java是20世纪90年代由Sun公司开发的面向对象的程序设计语言,Write once, Run anywhere的特点和JVM的工作模式是相契合的,它们给Java注入了强大的生命力。通过两个程序从编辑到运行的过程,揭示了Java程序编译和解释的运行机制,并对Java程序的基本结构建立了初步的认识。本讲只是一个Java语言基础的导引,要编写出自己的Java程序,必须学习Java中的数据类型和运算,学习程序的流程控制。

    五、思考与练习

    1. Write once, Run anywhere描述的是Java语言的什么特性? 2. 任何计算机都可以直接运行Java程序吗?

    3. Java程序可以直接编译成适用于本地计算机的机器码吗? 4. 不同的操作系统上可下载同样的Java VM版本安装吗? 5. 从哪里下载J2SE?

    6. 安装好J2SE后,安装目录为D:\JDK1.6,请问如何设置环境变量? 7. classpath的设置意义是什么?

    8. Java程序文件和Java字节码文件的扩展名分别是什么? 9. JCreator与JavaSE是一种怎样的关系? 10. 在JCreator中如何编译和运行Java 程序? 11. Java程序中的类名通常由大写还是小写字母开头? 12. Java中的常用修饰词和变量通常由大写还是小写字母开头? 13. 编写一个Java程序,显示输出你的邮箱和电话号码。 第二讲 Java中的数据类型和运算

    任何语言都需要操纵和处理数据,数据是有类型的,不同的数据类型有不同的运算方式。本讲主要讨论Java语言的数据和运算,主要内容有:

    Java输入/输出的初步运用 Java的标识符和保留字 Java的基本数据类型 Java基本数据类型转换 Java中的运算

五、基础

    一、Java输入/输出的初步运用大多数程序都要输出数据,有一部分程序需要在运行时输入数据。

如这样一个问题:读取一个整数,输出该数的平方。

    这应该是一个很简单的问题吧?它需要用户先输入一个数,程序输出该数平方的结果。本节专门针对上面这个问题。一通百通,由此及彼。把它解决了,我们就了解了Java的输入/输出方法,然后能着手写出实用的程序。

    1. 问题解析

    问题复述:读取一个整数,输出该数的平方。 Java可将该问题分解成如下几个步骤: 创建一个来自标准输入设备的扫描器(①); 从扫描器上读取一个整数(②); 做求平方运算,自乘一次即可; 将运算结果向标准输出设备输出(③)。

    其中,①②③皆是存疑的标识,通过下面的程序对照来步步解惑。 2. 程序解决

    按如上步骤,对问题编程解决。

    1. [Square.java]

    2. import java.util.Scanner; 3. public class Square {

    4. public static void main(String[] args){

    5. Scanner sc = new Scanner(System.in); //① 6. int n = sc.nextInt(); //② 7. int s = n * n;

    8. System.out.println(s); //③ 9. } 10. }

    程序的输出结果是:

    1. 12(用户交互输入) 2. 144(显示输出)

    从main方法开始读起,语句后标示的数字符号注释即是对问题解析中存疑的解答。解①:扫描器的类型是Scanner,来自标准输入设备(默认键盘)的扫描器可由new Scanner(System.in)创建。

    解②:可通过扫描器的规定方法获取数据,如用nextInt方法取得整数,用nextDouble方法取得双精度实数,类似的方法有很多,可取得各种不同类型的数据。

    解③:输出数据的方法是System.out.println(……),其中括号中的省略号为输出内容,输出内容可由字符串与数值数据多项组成,项与项之间直接用“+”连接即成。

    依照上一讲的说明,该程序的第二行中,class前加了public一词,所以程序文件必须命名为Square.java。

    3. 程序解析扩展

    在前面对程序作了基本的解析,但这些解析还不能令你透彻地理解程序。要透彻地理解,还需要掌握一些面向对象的基本知识,这里只作蜻蜓点水式的说明:

    1)Scanner是一个类,它在java.util包中,所以本程序的首行为“import java.util. Scanner;”,意为载入此类;

    2)要创建一个扫描器,需要给Scanner指出扫描源,如new Scanner(System.in); 3)Scanner扫描器拥有很多扫描输入数据的方法,如nextInt()即是其中之一; 4)System为系统类,它在java.lang包中,该包在程序编译时自动载入,故不用在程序开头加对应的载入语句;

    5)System.out为数据标准输出流,该流拥有print和println方法,print方法的意义是不换行输出,println是换行输出。

    二、Java的标识符和保留字

1. 标识符

    Java程序中的类、属性、方法、对象、变量等元素都应有自己的名称,各元素的名称通称为标识符。

    Java标识符定义规则:由字母、数字、_和$组成;开头字符必须是字母、下画线或$。标识符定义采用三原则:见名知义、规范大小写、不可用Java保留字。

    例如,从以下字符串中挑出合法的Java标识符。

    1. 2tow Mary5 else Hello world

    2. bob do cheese_eat Hello!

    合法的标识符:Mary5、bob、cheese_eat。非法标识符:2tow(开头字符不可为数字)、Hello world(标识符中不可有空格)、Hello!(!不可作为标识符的组成字符)、else和do(皆为Java保留字)。

    合法的标识符是符合定义规则的字符串,不符合定义规则的字符串则是非法标识符。另外,标识符对字母大小写敏感,如myname与Myname是两个不同的标识符。

    2. 保留字

    保留字(reserved word),是指Java语言规定了特定含义的标识符。对于保留字,用户只能按照系统规定的方式使用,不能自行定义。

    数据类型相关的保留字:boolean、int、long、short、byte、float、double、char、class和interface。

    流程控制相关的保留字:if、else、do、while、for、switch、case、default、break、continue、return、try、catch和finally。

    修饰符相关的保留字:public、protected、private、final、void、static、strictfp、abstract、transient、synchronized、volatile和native。

    动作相关的保留字:package、import、throw、throws、extends、implements、this、super、instanceof和new。

    其他保留字:true、false、null、goto和const。 需注意,保留字一律用小写字母表示。 三、Java的基本数据类型(1)

    在Java中,每个存放数据的变量都是有类型的,如:

    1. char ch; 2. float x; 3. int a,b,c;

    ch是字符型的,就会分配到2个字节内存。不同类型的变量在内存中分配的字节数不同,同时存储方式也是不同的。所以给变量赋值前需要先确定变量的类型,确定了变量的类型,即确定了数据需分配内存空间的大小,数据在内存的存储方式。

    1. Java中的数据类型

    Java中的数据类型有基本数据类型和引用数据类型两大类,图2-1呈现了Java中数据类型的概貌。本讲就基本数据类型进行讨论,引用数据类型将在下一篇中论述。

    以下讨论每一种数据类型时,对常量和变量作分别说明。所谓常量,就是直接的值;而变量则是放置常量的容器,除了放置常量之外,也可以给变量一个运算式,变量中的值是可变的。

    2. 布尔型—boolean

    布尔型又名逻辑型,它是最简单的数据类型,在流程控制时常会用到。有C++编程经验的学习者,要特别看清,Java中的布尔型数据不对应于任何整数值。

    布尔型常量:true和false。需要注意的是,布尔常量的组成字母一律都是小写的。 布尔型变量:以boolean定义的变量,如:

    1. boolean b = true; //定义变量b是boolean,且值为true

    3. 字符类型—char (1)字符常量

    字符常量指用单引号括起来的单个字符,如‘a’,‘A’。

    请特别注意,字符的定界符是单引号,而非双引号。除了以上所述形式的字符常量值之外,Java还允许使用一种特殊形式的字符常量值,这通常用于表示难以用一般字符来表示的字符,这种特殊形式的字符是以一个“\”开头的字符序列,称为转义字符。Java中的常用转义字符见表2-1。

    表2-1 Java中的转义字符(2)字符变量

    以char定义的变量,如char c='a';

    要特别加以说明的是,Java的文本编码采用Unicode集,Java字符16位无符号型数据,一个字符变量在内存中占2个字节。

    例1:编程测试十六进制数41、51对应的字符,并相隔一个tab位输出。

    分析:已知十六进制数,求字符。根据表2-1,可用'\uxxxx'的转义字符形式来表示所求字符,然后直接输出即可。     1.

[HDTest.java]

    class HDTest{

    public static void main(String[] args){ 
        char a='\u0041'; 
        char b='\u0051';

    System.out.println(a+" "+b);

    //字符之间以若干空格相间 
     } 
}

    程序运行结果:A Q

三、Java的基本数据类型(2)

4. 定点类型(整型)

    定点类型包括了字节型、整型、短整型和长整型,它们在内存中虽然占据的字节数互不相同,但它们的存储方式是同样的,所以这里把这些类型归并在一起讨论。“定点”的意思是把小数点定在末尾,小数点后没有数字的数据,Java中通常把它们称为整数。

    (1)定点常量

    定点常量是整型常数,它可用十进制、八进制、十六种进制三种方式来表示。 十进制定点常量:如123、-456、0。

    八进制定点常量:以0前导,形式为0dd……d。如0123表示十进制数83,-011表示十进制数-9。

    十六进制定点常量:以0x或0X开头,如0x123表示十进制数291,-0X12表示十进制数-18。

    (2)定点变量

    定点变量即整型变量,可细分成字节型变量、整型变量、短整型变量和长整型变量四种。表2-2对各种定点变量的开销内存字节数和数值范围作简要说明。

    表2-2 关于整型变量的说明

    需要注意的是,如果要将一定点常量赋值给一个定点变量,需要查验常量是否在该变量的表达范围内,如超出范围程序会编译出错。

    如:

    1. byte b = 200; //JCreator编译时错误信息是“可能损失精度”

    例2:阅读程序,分析其运行结果。

    1. [OHTest.java]

    2. class OHTest{

    3. public static void main(String[] args){ 4. int x = 010;

    5. System.out.println("x = "+ x); 6. int y = 0x10;

    7. System.out.println("y = " + y);8. } 9. }

    程序运行结果略,请思考并调试验证。 5. 浮点型(实型) (1)浮点常量

    即带小数点的实型数值,可以由直接带小数点的数值和科学计数法两种形式来表示: 带小数点的数值形式:由数字和小数点组成,如0.123、.123、123.、123.0。 科学计数法表示形式:由一般实数和e±n(E±n)组成,如12.3e3、5E-3,它们分别表示12.3×103和5×10-3。需要注意的是,e或E之前必须有数字,且e或E后面的指数必须为整数。

    (2)浮点变量

    浮点变量有单精度变量和双精度变量之分,不同的精度开销的内存字节数和表达的数值范围均有区别。两种浮点变量占内存字节数和数值范围见表2-3。

    表2-3 单精度变量和双精度变量简要说明

    浮点常量也有单精度和双精度之分,前面列出的常量均是双精度常量,如果要特别说明为单精度常量,可以数据末尾加上f或F作为后缀,如12.34f。如果要特别指明一个浮点常量是双精度常量,数据末尾不需要添加后缀,或者在数据末尾加上d或D作为后缀,如12.34d。

    例3:输入一个圆的半径,求圆面积。

    分析:圆半径在编写程序时是不确定的,其值在程序运行时输入,这样程序就比较通用,可以处理不同半径的求面积和周长问题。这就涉及数据输入的问题,参照本讲第一节,输入数据通过Scanner扫描器解决。

    1. [CircleArea.java]

    2. import java.util.Scanner; 3. class CircleArea{

    4. public static void main(String[] args){5. Scanner sc = new Scanner(System.in); 6. double r = sc.nextDouble(); 7. double area = Math.PI * r * r; 8. System.out.println(area); 9. } 10. }

    四、Java基本数据类型转换

    除了布尔型数据外,其他定点类型的数据和浮点类型的数据可以混合在一起进行运算,不同类型数据运算的结果是何种类型的呢?数据可由一种类型转换成另一种类型吗?在这一讲里这些疑问都将得到解决。

    1. 自动类型转换

    定点和浮点类型都可看作是数值型数据,当不同的数值型数据运算时,有一个内在的规则:先统一为同一类型,再进行运算。结果就为运算前统一的类型。这里的“统一”就是自动类型转换。

    自动类型数据转换总是从低级到高级进行,byte、char、short的级别最低,double的级别最高,具体如图2-2所示。

    byte、char、short型数据只要参与运算,就首先将类型转为int后进行运算,所以即使short型数据之间的运算,运算结果也是int型。如果int型数据与float型数据运算,int型数据会自动转换成float型,运算结果也为float型。

    例4:如有以下变量定义,请回答算式:x + y、 x + y + z、 a + b、 a - x - y、x + c的结果分别是何种类型。

    1. int x; 2. byte y; 3. long z; 4. float a; 5. double b; 6. char c;分析:x + y的结果应为int型,x + y + z的结果为long型,a + b的结果为double型,a - x - y的结果为float型,x + c的结果为int型。

    2. 强制类型转换

    不同类型数据之间的运算和赋值时,低级别类型的数据可以自动转换成高级别类型的数据。欲让高级数据转换成低级数据,需用到强制类型转换,其形式是:

    (类型)数据

    数据为需要类型转换的常量、变量或表达式。括号中的类型为数据要转换成的类型。 如:int x = 3.5; //编译出错,高级别的数据不能给低级别的变量赋值 int x = (int)3.5; //将3.5强制转换成int型数据,后给同级别的变量x赋值

    例5:阅读程序Char_Int1.java、Char_Int2.java和Float_Int.java,分析它们的运行情况。

    1. [Char_Int1.java]

    2. class Char_Int1{

    3. public static void main(String[] args){ 4. char y = 'a';

    5. System.out.println( y ); 6. } 7. }

    分析:程序输出结果为a,本程序无数据运算。

    1. [Char_Int2.java]

    2. class Char_Int2{

    3. public static void main(String[] args){ 4. int x = 2; 5. char y = 'a';

    6. System.out.println(y + x); 7. } 8. }

    分析:程序中有x + y的运算,如图2-2所示,char型首先转换成int型,即字符对应的ASCII码值。而字符a对应的ASCII码为97,故程序结果为99。

    思考:如何修改程序使之输出结果为字符c?

    1. [Float_Int.java]2. class Float_Int{

    3. public static void main(String[] args){ 4. int x=(int)5.2f; 5. float y = x;

    6. System.out.println(x + " " + y); 7. } 8. }

    程序运行结果:5 5.0 五、Java中的运算(1)

    数据的运算通过运算符实现,Java语言提供了丰富的运算符,在本讲中将讨论算术运算、赋值运算、条件运算、关系运算和逻辑运算,以及各种运算符的优先级别。

    1. 算术运算

    算术运算由算术运算符完成,可以实现最基本的数值运算。算术运算符可分为双目和单目两类,双目运算符需要两个操作数参与,有加、减、乘、除、取余五种,见表2-4。

    表2-4 双目运算符

    表2-4中的op1与op2是两个操作数,它们可以是任意数值型的数据。特别要说明的是Java中的“%”运算与C++有别,它可对浮点数进行,符号同第一个操作数。如52.3%10的结果是2.3,-12%-5的结果是2。

    此外,Java对符号“+”运算进行了扩展,它不仅可以对数值型数据进行加法运算,还可以进行字符串之间、数字与字符串之间的拼接。如System.out.println(“s= “ + 4*5);语句将输出s = 20的结果,括号中项与项之间的“+”就起了拼接的作用。

    相对双目运算符,还有单目运算符,见表2-5,它们只对一个操作数进行运算。 表2-5 单目运算符表2-5中的op是一个操作数,对于“前缀+”和“前缀-”,op可以是任意数值型的常量、变量和表达式。如果是常量应是无符号的,如-3,如果带符号则该常量应带上小括号,如-(-3),结果负负得正,为3。

    表2-5中的op对于前后缀的“++”和“--”,就不能是常量和表达式了,只能是变量。5++与++(a+b)均是错误用法。前后缀的“++”和“--”通常也称为自加、自减。在使用时另外还要注意如下几点:

    ++与--运算时结合方向自右向左,-i++相当于-(i++); 两个+号(或-号)之间不能有空格; 应避免使用复杂的表达式。

    算术表达式即是用算术运算符与括号将运算对象连接起来的、符合Java规则的式子。就算术运算符之间,运算级别以“先*、/、%,后+、-,左结合”的原则进行,如n*-2、-n/-2。

    例6:阅读程序,分析程序运行结果。

    1. [TestMod.java]

    2. class TestMod{

    3. public static void main(String[] args){ 4. int x = 3, y = 10;

    5. System.out.println(y-- % ++x); 6. System.out.println(-y % -x); 7. } 8. }

    分析:x和y值的变化如程序右侧表2-6所示,第一行输出时,y取用10进行模运算,x先自加为4,结果为2;y接着自减到9,进行第二行输出,结果为-1。2. 赋值运算

    将数据保存到变量中,这个过程就是“赋值”,所以赋值运算也是最基本的运算,赋值运算符号即为通常的等于符号“=”。Java中的赋值运算可分为基本赋值与复合赋值两种。

    (1)基本赋值 基本赋值运算形式:

    1. <变量> = <表达式>

    其作用是将“=”右边表达式的值赋给左边的变量。表达式也可以是直接的常量或变量。该式加上分号即为赋值语句。

    特别要说明的一点是,“=”右边的表达式的级别不能高于变量所定义类型的级别(数值型的级别如图2-2所示),否则要有强制转换的说明。而如果表达式类型与变量类型是不可互转的,这样的赋值运算在编译时将出错。

    例7:阅读程序,理解赋值运算。

    1. [AssignTest.java]

    2. class AssignTest{

    3. public static void main(String[] args){ 4. int a,b;

    5. int c = (a = 5) + ( b = 13);

    6. System.out.println(a + " " + b + " " + c); 7. } 8. }

    程序运行结果为:5 13 18 五、Java中的运算(2) (2)复合赋值

    复合赋值意味着的是运算且赋值,其形式:

    1. <变量><简单运算符> = <表达式>

    表2-7通过示例对复合赋值进行了简要说明。表2-7 复合赋值示例说明

    复合赋值化解成基本赋值式为: <变量> = <变量><简单运算符>(<表达式>),表达式加上括号意指优先运算。

    3. 关系运算

    关系运算亦即比较运算。既然是比较就需要两个操作数参与。Java提供的关系运算符及其示例说明见表2-8。

    表2-8 关系运算符及其说明

    由表2-8知关系运算式的通常形式是:

    1. op1 <关系运算符> op2

    表中的op1与op2是两个可以比较的操作数,它们可以是基本数据类型的,也可以是复合类型的。目前暂只讨论前者。下面有几点说明在编程时需要注意:

    “==”不要写成“=”;

    任何类型的两个数据都可以通过“==”或“!=”来比较是否相等; 浮点数的比较小心慎用;

    关系运算的结果是true和false,而非1或0;关系运算符优先级低于算术运算符优先级,高于赋值运算符优先级。 4. 逻辑运算

    逻辑运算可以表达复合的条件,逻辑运算可以对结果是布尔型的数据进行复合或否定。逻辑运算符只有三个,关于它们的说明见表2-9。

    表2-9 逻辑运算符及其说明

    表2-9中的op1、op2、op皆是布尔型数据。与其他表达式不同的一点是,逻辑运算表达式中,不是每一个逻辑运算符都一定进行运算。在“&&”与运算时,只要前一个操作数的结果是false,结果就已确定为false,后面的运算就被忽略;在“||”或运算时,只要前一个操作数的结果是true,结果也就确定为true,后面的运算同样被忽略,这称为逻辑运算的截断性。

    例8:阅读程序,理解逻辑运算的截断性。 [CutOffTest.java]

    1. class CutOffTest {

    2. public static void main(String[] args){ 3. int f = 0;

    4. if (f!=0 && 3/f>5)

    5. System.out.println("true"); 6. else

    7. System.out.println("false"); 8. } 9. }

    分析:if语句中的3/f>5的运算会发生除0溢出错误,因为f!=0的结果是false,后面所遇又是“&&”,根据逻辑运算的截断性,其后的表达式被忽略,所以程序可正常运行得到结果,结果为false。

    加入逻辑运算符后,优先级别排序是:非运算(!)、算术运算、关系运算、逻辑与(&&)、逻辑或(||)、赋值(=)。

    5. 条件运算条件运算可根据条件取值,运算符号由间隔的双字符组成“? :”。条件运算式形式是:

    1. e1 ? e2 : e3

    式中的e1为条件,应是布尔型数据,e2和e3可以是任意类型、但必须类型一致的数据。若条件e1为真,则条件运算结果为e2的值;若条件e1为假,则条件运算结果为e3的值。下面语句可以求a和b中的较大数,并赋值给变量max:

    1. max = a > b ? a : b;

    6. Java运算符的优先级

    当运算趋于复杂时,表达式中可能会出现多种运算符,只有理解了Java运算符的优先级,才能运用得当,所得即所想。

    Java运算符的优先级见表2-10。 表2-10 Java运算符的优先级

    本讲属于Java程序设计基础的部分,介绍了Java语言标准设备的数据输入/输出方法、Java中的数据和运算。继续学习下一讲的程序流程控制,你就将初步具备程序设计的能力。

    六、思考与练习

    1. 如何在程序运行时交互输入数据? 2. 一个数字组成的字符串如何转化成整数? 3. Java程序如何向字符窗口输出数据? 4. 在Java中一个字符数据开销字节数是多少? 5. 在Java中怎样给出一个八进制整常数?6. 在Java中怎样给出一个十六进制整常数? 7. 在Java中如何输出数据?

    8. Java表达整型的数据类型与C相比异同点是什么? 9. 如何给出一个单精度常数?

    10. 字符常量和字符串的定界符分别是什么? 11. 在Java中一个整型数据占字节数是多少? 12. 在Java中用什么类型的变量存储一个逻辑值? 13. 阅读程序,分析程序运行情况。 (1)

    1. class Test1{

    2. public static void main(String[] args){ 3. char a = '\u0041'; 4. int b = a; 5. float c = b; 6. double d = c;

    7. System.out.println(a + "\t" + b + "\t" + c + "\t" + d); 8. } 9. }

    (2)

    1. class Test2{

    2. public static void main(String[] args){ 3. double e = 65.5; 4. float f = e; 5. int g = f; 6. char h = g;

    7. System.out.println(e+ "\t"+ f+ "\t"+ g+ "\t"+ h); 8. } 9. }

    (3)

    1. class Test3{

    2. public static void main(String[] args){ 3. System.out.println(10 % 3);4. System.out.println(10 % -3); 5. System.out.println(-10 % 3); 6. System.out.println(-10 % -3); 7. } 8. }

    (4)

    1. class Test4{

    2. public static void main(String[] args){ 3. char x = '4'; 4. int y = 4;

    5. if (x==y)System.out.println(y); 6. else System.out.println((char)y); 7. } 8. }

    14. 输入两个整数,求平均数。

七、Java结构化编程

    只有少数问题,诸如上一讲的“读取整数求平方”,可以通过若干语句的顺序执行得到结果。大多数任务需要运用到分支和循环才得以解决。本讲主要讨论Java程序的结构化编程和流程控制,主要内容有:

    分支结构(if, switch)

    循环结构(while, do-while, for) 循环嵌套和循环控制(break, continue) Java结构化编程综合 一、分支结构(1)

    如果有这样一个问题“交互输入一个整数,若为正数求平方,若为负数求立方”,顺序执行的语句就无法解决了,此时要通过分支结构的程序来求解。

    Java像C++一样,可以通过if语句和switch语句来建立分支结构的程序。相对来说,if语句更常用一些,因为if可表达所有的条件分支情况,而switch语句也有着特别的妙处,在某些情况下,可以令程序更加简练清晰。

    1. if语句if语句是最基本的分支语句。它通过条件的直接判断,转向不同的程序流程,以此实现流程控制。

    (1)if语句的最简形式

    1. if ( 条件 ) 2. 语句块

    条件为boolean数据,语句块指一组语句,若语句块中的语句多于一条,则在头尾需要用成对的大括号标识。图3-1解析了该语句的执行流程。当条件为true时,执行语句块,条件为false时,则跳过语句块。

    这两条语句,保证max变量总是取得a和b中的较大数。 (2)if语句的基本形式

    1. if ( 条件 ) 2. 语句块1 3. else 4. 语句块2

    图3-2解析了if-else语句的执行流程。当条件为true时,执行语句块1,条件为false时,执行语句块2。只要执行到此if语句,总有一个语句块被执行。这是一个兼有输入和输出的问题,输入同样用Scanner扫描器解决,通过nextDouble()方法取得扫描到的double型数据。然后通过分支求y值。注意程序中所涉变量必须在使用之前定义类型。

    例2:闰年计算规律为:“四年一闰,百年不闰,四百年再闰”。输入一个年份,判断该年份是否为闰年。分析:能被4整除的年份通常是闰年,而如果该年份还能被100整除,则存疑了。需要继续考察该年份能否被400整除,若能则是,否则非闰年。这样闰年就有两种情况:直接能被400整除的年份、被4整除而不能被100整除的年份。

    [TestIf2.java]

    1. import java.util.Scanner; 2. class TestIf2{

    3. public static void main(String[] args){ 4. Scanner sc = new Scanner(System.in); 5. System.out.print("Year? "); 6. int year = sc.nextInt();

    7. if( year % 400 == 0 || year % 4 == 0 && year % 100 != 0) 8. System.out.println(year+" is a leap year."); 9. else

    10. System.out.println(year+" is't a leap year."); 11. } 12. }

    一、分支结构(2)

    如果遇到比以上示例复杂的问题,如y是一个三分支的函数,对x的取值范围需要考虑三种或更多的情况,此时if-else语句仍可以解决,那就是在语句块中继续嵌套if-else语句,形式如:

    1. if ( 条件1 ) 2. if ( 条件2 ) 3. 语句块1 4. else 5. 语句块2 6. else 7. 语句块3

    这样的嵌套理论可行,但程序的清晰性减弱,特别是嵌套层数在两层以上,就很容易出错。Java提供了if-else的扩展形式,可以自如应对多分支的问题。

    (3)if语句的扩展形式

    1. if ( 条件1 ) 2. 语句块1 3. else if ( 条件2 ) 4. 语句块25. ……

    6. else if ( 条件n ) 7. 语句块n 8. [else

    9. else语句块]

    其中,末尾中括号的else部分是可选的。如果无可选的else部分,而前面的各条件又都为false时,程序流程流经这条if语句,什么也不执行;否则,不管前面的条件怎样苛刻,总有一个、当然也只有一个语句块执行。流程解读如图3-3所示。

    例3:某企业工龄工资调整,工龄不到二年者不参与调整,其余员工中,工龄少于五年者按每年50元计算,工龄达五年少于十年者每年按65元计算,工龄达十年者每年按80元计算,工龄达十五年者每年按100元计算。此外,对达十二年以上者,额外增加200元。

    分析:本问题是一个五分支的处理,五种情况分别是:不到二年、过二年不到五年、达五年不到十年、达十年不到十五年、达十五年。“此外”部分放在最后考虑。

    [TestIf3.java]

    1. import java.util.Scanner; 2. class TestIf3{

    3. public static void main(String[] args){ 4. Scanner sc = new Scanner(System.in); 5. System.out.print("工龄? "); 6. int year = sc.nextInt();7. int num;

    8. if( year<2 ) num = 0;

    9. else if( year<5 ) num = year * 50; 10. else if( year<10 ) num = year * 65; 11. else if( year<15 ) num = year * 80; 12. else num = year * 80; 13. if( year>=12 ) num += 200;

    14. System.out.println(year + "\t" + num); 15. } 16. }

    2. switch语句

    switch是用基于整型数据的多分支判断。 switch语句形式:

    1. switch ( 表达式 ) { 2. case 值1: 语句组1; 3. case 值2: 语句组2; 4. ……

    5. case 值n: 语句组n; 6. [default: default语句组;] 7. }

    语句组指一组语句,与语句块不同的是头尾不需要用大括号括出。

    switch中的表达式结果必须是一个整型值,该值用来与后续的值1、值2、??、值n比较,如果值是相同的,则执行case后的语句组。之后不再判断,连续地执行下去,直到遇到break语句或switch运行完毕。switch表达式值与值1匹配的极端情况,将使所有的语句组都顺序执行。具体流程如图3-4所示。所以break语句对于switch语句是相当重要的,switch如好脾气的、不知拒绝的主人,而break就是当机立断的管家,流程至break就终止switch语句的执行,转到switch后的语句。

    例4 : 输入一百分制成绩, 输出对应的等级。90~100分的等级为‘A’,80~89分的等级为‘B’,70~79分的等级为‘C’,60~69分的等级为‘D’,60分以下的等级为‘E’。

    1. [TestSwitch.java]

    2. import java.util.Scanner; 3. class TestSwitch{

    4. public static void main(String[] args){ 5. Scanner sc = new Scanner(System.in); 6. System.out.print("Score ? "); 7. int scscore = sc.nextInt(); 8. char grade; 9. switch(score/10){

    10. case 9: case 10: grade = 'A'; break; 11. case 8: grade = 'B'; break; 12. case 7: grade = 'C'; break; 13. case 6: grade = 'D'; break; 14. default:grade = 'E'; 15. }

    16. System.out.println(score+"\t"+grade);17. } 18. }

    请思考一下,如果程序中无break语句,运行结果会是怎样? 二、循环结构

    程序经常需要重复一些操作,如生成一个有规律可循的数列、自然数累加等问题。循环结构正好用来解决这样的问题。在Java中,有while、do-while、for三条语句可用来设计循环结构的程序。

    1. while语句

    while语句是条件循环语句,根据条件是否成立,确定循环是否进行。

    1. while循环语句形式: 2.

    3. while ( 条件 ) 4. 语句块

    在循环体执行前先判断条件,只要条件成立,循环就继续。语句块即是重复的部分,称为循环体。语句块执行完毕再回到条件判断,直到条件不成立,流程转到下一语句。流程解析如图3-5所示。

    例5:求前100个自然数的和。

    分析:本题即求1+2+?+100,要设一个累加变量sum放置结果,在累加前需给sum设置初值,以后需不断在sum中加入递增的数,将此加数变量设为num,num的初值应为1,变化规则是每次递增1,当num超过100时,sum中的值即为所求结果。[TestWhile.java]

    1. class TestWhile{

    2. public static void main(String[] args){ 3. int sum = 0, num = 1; 4. while(num<=100){ 5. sum += num; 6. num ++; 7. }

    8. System.out.println("sum: " + sum); 9. } 10. }

    由此及彼,许多累加的问题都可仿照完成。

    设计一个循环时,要考虑到循环的终点,而循环体中应该可以不断地修正循环条件,让循环条件由开始的成立向不成立转化,此时循环便结束。不设置终点的循环会永无穷尽,即陷入死循环。

    2. do-while语句

    do-while循环与while循环很相近,区别只在于先判断还是先执行。 do-while循环语句形式:

    1. do

    2. 语句块 3. while ( 条件 );

    do-while语句流程解析如图3-6所示。大多数情况下while循环与do-while循环会得到一致的结果。惟一可能产生差异的是循环条件特别苛刻,第一次就不成立,此时while循环什么都不做,而do-while循环的循环体却会执行一次。例6:用do-while语句求前100个自然数的和。

    1. [TestDoWhile.java]

    2. class TestDoWhile{

    3. public static void main(String[] args){ 4. int sum=0,num=1; 5. do{

    6. sum += num; 7. num ++;

    8. }while(num<=100); //while后的分号不可缺 9. System.out.println("sum: " + sum); 10. } 11. }

    3. for语句

    for循环是一种计数循环,可以设置循环变量,用来遍历某个范围的值。 for循环语句形式:

    1. for ( 语句块1; 条件; 语句块2) 2. 语句块3

    for语句流程解析如图3-7所示。for中有三项,它们分别用分号相间,其中语句块1只在循环起始执行了一次,而没参加具体的循环。语句块3是循环体,而语句块2是每次循环完毕执行的部分。for语句同while一样也是先判断后循环的语句,可用while来改写如下:

    1. 语句块1;

    2. while ( 条件 ) {当然这样的改写只是帮助对for语句的理解,相对来说,for语句还是更简明和更有效率的。

    例7:用for语句求前100个自然数的和。

    1. [TestFor.java]

    2. class TestFor{

    3. public static void main(String[] args){ 4. int sum,num;

    5. for(sum=0, num=1; num<=100; num++) 6. sum += num;

    7. System.out.println("sum: "+sum); 8. } 9. }

    语句块1可用来初始化一个或多个变量,如果是多个变量取不同的初值,可在赋值表达式间以逗号相间。语句块1、条件、语句块2三项是可选的,最简的for语句形式是for(;;),这就相当于while(true),它们设定了一个永真循环,很有死循环的嫌疑。下一节的学习将澄清迷雾,我们会认识到除了循环条件外,在循环体内也可以设置中途退出的机制。

    三、循环控制和循环嵌套循环控制是除了循环条件之外,控制循环是否进行的一个机制,这给处理循环问题带来了灵活性。循环体内的语句块可以是顺序执行的语句,可以是分支结构的语句,也可以是循环语句,循环中含循环,就是循环嵌套。

    1. 循环控制

    循环控制由break语句和continue语句实现。 (1)break语句

    break语句很利落简单,语句形式: break;

    break语句除了适用于switch外,也适用于for、while以及do-while三种循环语句,其作用是结束循环,程序流程至这些语句后的第一句。通常break语句配合条件语句一起使用。

    例8:求1+2+3 +?+ N < 1000的N的最大数。

    分析:这是一个自然数累加计算加判断的问题,加多少项是预先不知的,或者正是所求的,所以不管是用哪个循环语句来处理,条件的地方均无法明确给出。这就需要在循环体中边加边判断,如果结果有了,中途退出循环。

    [TestBreak.java]

    1. class TestBreak{

    2. public static void main(String[] args){ 3. int sum = 0, num = 1; 4. while( true ){ 5. sum += num;

    6. if( sum>1000 ) break; 7. num ++ ; 8. }

    9. System.out.println("N: " + (num-1)); 10. } 11. }

    (2)Continue语句 continue语句形式: continue;continue语句,也称短路语句。它适用于for、while以及do-while语句中,其作用是忽略其后的语句,中止当前循环,流程转至循环起始处,开始下一次循环。

    例9:阅读程序,分析程序运行结果。

    1. [TestContinue.java] 2.

    3. class TestContinue{

    4. public static void main(String[] args){ 5. for(int m = 1; m <= 10; m ++){ 6. if( m%2 == 0 ) continue; 7. System.out.print(m + "\t"); 8. } 9. } 10. }

    2. 循环嵌套

    在解决复杂一些的问题时,需要在循环里继续设置循环语句,这就是循环的嵌套。外层的循环称为外循环,内层的循环称为内循环。如输出二维矩阵的问题,用循环嵌套就很容易解决。

    例10:阅读程序,分析程序运行流程。

    1. [Matrix.java] 2.

    3. class Matrix {

    4. public static void main( String[] args ){ 5. for( int i=1; i<=3; i++ ) { 6. for ( int j=1; j<=5; j++)

    7. System.out.print(i*j + "\t"); //内

    循环体

    8. System.out.println(); //换行 9. } 10. } 11. }

    程序分析:i是外循环变量,当i取得一个值,循环体(斜体部分的代码)执行一次。其中有两条语句,一条是for循环语句(内循环),另一条是换行语句。当循环体执行时,即内循环变量j从初值到终值遍历一次,进行输出。i增值换下一个时,先换行。

    本程序的输出结果是:1. 1 2 3 4 5 2. 2 4 6 8 10 3. 3 6 9 12 15

    例11:输出一个三角形形式的九九乘法表。

    1. 1×11=1 2. 2×1=2 2×2=4

    3. 3×1=3 3×2=6 3×3=9

    4. 4×1=4 4×2=8 4×3=12 4×4=16

    5. 5×1=5 5×2=10 5×3=15 5×4=20 5×5=25

    6. 6×1=6 6×2=12 6×3=18 6×4=24 6×5=30 6×6=36 7. 7×1=7 7×2=14 7×3=21 7×4=28 7×5=35 7×6=42

    7×7=49

    8. 8×1=8 8×2=16 8×3=24 8×4=32 8×5=40 8×6=48

    8×7=56 8×8=64

    9. 9×1=9 9×2=18 9×3=27 9×4=36 9×5=45 9×6=54

    9×7=63 9×8=72 9×9=81

    分析:这与前面矩阵输出的问题有些相像,同样也是输出多行的问题。乘法表有九行,可用循环变量i来记录行数(1~9行),第1行,有1个乘法算式;第2行,有2个乘法算式;第i行便有i个乘法算式。对于确定的第i行,如何来输出这i个算式呢?这又是一个重复处理的问题,可用内循环来解决。内循环变量设为j,j的变化从1到i。

    [MutiTable.java]

    1. class MutiTable{

    2. public static void main( String[] args ){ 3. for( int i=1; i<=9; i++ ) { 4. for ( int j=1; j<=i; j++)

    5. System.out.print( i + "*" +j+ "=" + i*j + "\t"

    );

    6. System.out.println(); 7. } 8. } 9. }

    以上程序巧妙的是,循环变量i和j正巧是每个乘法算式的被乘数和乘数。 四、Java结构化编程综合

    本节通过程序设计实例,来进一步掌握Java结构化编程方法。例12:输入一月份,求该月的天数。

    分析:不同的月份有不同的天数,这需要判断后才能确定。把月份归为三类,30天的月份有4、6、9、11月份,28或29天(由年份再确定)的月份是2月份,其余皆为31天。这是一个多分支判断的问题,可用if或switch语句解决,根据月份判断天数部分用switch语句代码更简捷。

    [Monthdays.java]

    1. import java.util.Scanner; 2. class Monthdays{

    3. public static void main(String[] args){ 4. int month,days;

    5. Scanner sc = new Scanner(System.in); 6. System.out.print("Month? "); 7. month = sc.nextInt();

    8. if(month<1 || month>12){ //若输入数据非月份数 9. System.out.println("error data");

    10. System.exit(0); //退出运行 11. }

    12. switch(month){

    13. case 4: case 6: case 9: case 11: days = 30;break; 14. case 2: //2月份需要输入年份进一步判断 15. System.out.print("Year? "); 16. int year = sc.nextInt();

    17. if(year%400==0 || year%4==0 && year%100!=0) 18. days = 29; 19. else days = 28; 20. break;

    21. default: days = 31; 22. }

    23. System.out.println("days: "+days); 24. } 25. }

    程序运行中途要强制退出,可以用“System.exit(0);”语句。本例中若输入的年份数据是不合理的数据,程序输出error data后,便退出结束运行。

    例13:输入一个自然数,判断该数是否为素数。分析:先确认什么样的数为素数。根据数学定义知,一个自然数除了1和本身之外没有其他的因子,该数便为素数。2专门规定为素数,且是最小的素数。对于自然数n,我们只要用2到n-1去测试,如果它们中没有一个是n的因子,n就为素数,否则n不是素数。

    [PrimeTest.java]

    1. import java.util.Scanner; 2. class PrimeTest{

    3. public static void main(String[] args){ 4. Scanner sc = new Scanner(System.in); 5. System.out.print("number? ");

    6. int n = sc.nextInt(); //n为被测数 7. int i; //i为1和本身外可能的因子 8. for(i=2;i<n;i++)

    9. if(n%i == 0)break; //i是n的因子,n非素数 10. if(i == n) //所有可能的因子全非n的因子 11. System.out.println( n + " is a prime number." ); 12. else

    13. System.out.println(n + " is not a prime number"); 14. } 15. }

    例14:求所有三位素数。

    分析:本题是上题的拓展。不是判断某一个数,而是判断所有三位数。这就需要用一个循环变量遍历三位数,因为所有的三位偶数都非素数,所以可直接遍历三位奇数。对于确定的三位数判断其是否为素数的方法同上。

    [PrimeNumbers.java]

    1. class PrimeNumbers{

    2. public static void main(String[] args){ 3. int i,n;

    4. for( n = 101; n<1000; n+=2 ){ //n遍历所有三位奇数 5. for( i=2; i<n; i++) 6. if( n%i == 0 )break;

    7. if( i==n )System.out.print( n + "\t"); 8. } 9. } 10. }

    程序运行结果:1. 101 103 107 109 113 127 131

    137 139 149

    2. 151 157 163 167 173 179 181

    191 193 197 3. …

    4. 983 991 997

    例15:输出如下菲波那契数列的前20项,并求其和。

    1. 1,1,2,3,5,8,13……

    分析:菲波那契数列的前两项均为1,以后的每一项都是前两项之和。这是一个重复求和处理的问题,可用循环解决。循环次数是所要求的项数18。对所有项求和的问题可以设置一个累加器变量sum,初值为前两项之和,后在循环中每求得一新项,即将该项加进sum。

    [Fei.java]

    1. class Fei{

    2. public static void main(String[] args){ 3. int a,b,c,sum;

    4. a = b = 1; //a,b为前两项,均为1 5. sum = a + b; //累加器变量,设初值 6. System.out.print( a + "\t" + b ); 7. for( int i=1; i<=18; i++ ){

    8. c=a+b; //生成的新项置放在变量c中 9. System.out.print("\t" + c); 10. sum += c;

    11. a = b; //前两项后移一个数 12. b = c; 13. }

    14. System.out.println("\tsum=" + sum); 15. } 16. }

    程序运行结果:

    1. 1 1 2 3 5 8

    13 21 34 55

    2. 89 144 233 377 610 987

    1597 2584 4181 6765 3. sum=17710本讲介绍了Java语言的结构化编程,在main方法中的代码段总是由三种基本结构组成:顺序结构、分支结构和循环结构。分支结构通常用if或switch语句实现,循环结构常用while、do-while或for语句实现。在循环结构中可以继承包含循环,这即是循环嵌套,也称为多重循环,我们可用多重循环解决比较复杂的问题。break语句可以安排在switch和三种循环语句中,它总是会终止当前的语句。continue语句可以放在循环语句中,它只是结束当前循环,而并不会终止循环。

    至此,我们已初入Java之门,可以解决一些基本的数据处理问题了。

    思考与练习

    1. 求150内的奇数之和。 2. 输入一个自然数,求N!。 3. 用循环嵌套的方法输出如下图案:

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值