第一次作业
第1章 实验 -- JAVA 入门
1.1 实验目标
以下的实验是针对没有任何编程基础的练习者设计的。实验的目的在于:
(1) 安装配置基本的JAVA程序运行环境;
(2) 练习使用Java 2 SDK 编译器;
(3) 了解简单的编程概念和Java程序的不同类型,学习JAVA语句的基本语法;
(4) 了解SDK 编译器显示的错误信息的含义。
1.2 实验说明
本章实验教程将指导安装JAVA程序的运行环境,一步一步地指导练习者编辑(Edit),编译(Compile)和运行(Run)一些入门级的JAVA程序,并解释相关的一些基础的JAVA语法(Syntax)。实验中,练习者将改变正确代码,观察代码错误时JAVA编译器显示出的相应的错误信息。 根据作者JAVA教学的经验,理解错误信息的含义是相当重要的,这能帮助程序员迅速定位代码语法错误(Syntax Error)。当然,现在有大量的JAVA IDE(Integrated Development Environment,集成编程工具),可以帮助程序员定位语法错误,甚至自动改正语法错误,如Eclipse, Netbeans, JBuilder。 在本次实验中, 我们不主张使用这些IDE。 对于JAVA编程语言的初学者, 使用简单的JAVA编码工具, 如记事本, Editplus, 一个一个字符地键入JAVA代码能帮助我们尽快熟悉JAVA基础语法。
以下的实验分为三种类型, 每个练习前面有一个字母的标注:
D - 例程, 表示这是一个例子, 要求练习者阅读指南和代码;
I - 交互式练习, 练习者完成实验指定的简单任务,如修改部分代码, 观察程序运行时的变化等;
W - 热身练习, 练习者的编程工作量逐渐加大。
还有一种练习类型, 将在下一实验中涉及到:
P - 完整编程,要求练习者根据要求,完成完整的JAVA程序。
1.3 实验准备
从本实验教程光盘中拷贝Lab01文件目录到本地磁盘, 如C: 盘。Lab01 文件目录中将包含本次实验所需的所有资料。Lab01的相关资料也可以从本实验教程的网站下载。
1.4 实验任务
实验1.4.1: (I)JAVA环境配置方法
JAVA是面向对象的编程语言,JDK(Java Development Kit, Java开发工具包)作为其开发包,可以开发Web应用及各种类型的桌面程序。JDK是编写Java程序的基础,它集成了编译JAVA源程序的
1
编译器、运行JAVA类文件的解释器等必备工具。
JDK的版本分为三类:
(1) J2ME(Java 2, Micro Edition): 针对消费类电子产品(如移动电话、可视电话等)的软件开发
的高度优化的Java运行环境。
(2) J2SE(Java 2, Standard Edition):SUN公司针对桌面开发以及低端商务计算解决
而开发
的版本。
(3) J2EE(Java 2, Enterprise Edition):是一种利用Java 2平台来简化企业解决方案的开发、
部署和管理相关的复杂问
的体系结构。J2EE的基础是J2SE,J2EE不仅巩固了
版中的许
多优点,同时还提供了对EJB、Servlet、JSP以及XML技术的全面支持。
我们目前的实验环节需要安装J2SE,实验的内容也是基于J2SE的最新版本J2SE 5.0。步骤如下:
,. 下载和安装JDK。
整个实验中我们采用SUN公司发布的JDK1.5(开发代号猛虎tiger),所对应的平台有Linux、Solaris和Windows等等。目前最新版本JDK下载地址:。教程中所有的实验环境都是基于Windows2000/XP操作系统的。
进入SUN公司的JDK下载页面,如图1.1所示,点击Download JDK 5.0,接受
。
图1.1 JDK5.0 下载链接
选择下载基于Windows平台的JDK5.0, 点击jdk-1_5_0_07-windows-i586-p.exe选择离线安装,多语言(Windows Offline Installation, Multi-language), 如图1.2所示。
图1.2 Windows平台的JDK5.0下载链接
从SUN官方服务器下载JDK有点慢,需要多等一会儿。下载过程中有可能出现断网,可使用网际快车(FlashGet)等支持断点续传的工具下载。本实验教程光盘中包含了J2SE5.0 Update7,可选择从光盘直接安装。
下载完成后,双击jdk-1_5_0_07-windows-i586-p.exe进行安装,安装过程中程序会要求选择安装路径,JDK默认安装目录在C:\Program Files\Java\jdk1.5.07。当然,练习者也可更改默认安装目录。在此练习中,JDK安装目录使用安装程序默认值,安装过程中一律采用默认值。
2
,. 配置环境变量。
软件安装结束后开始配置机器的环境变量。具体的设定方法: 右键点击我的电脑->属性->高级->环境变量,然后修改系统变量框里的值,如图1.3所示。
图1.3 环境变量选项卡
Windows下JAVA用到的环境变量主要有3个,JAVA_HOME、PATH 和 CLASSPATH。
JAVA_HOME指向的是JDK的安装路径,如C:\Program Files\Java\jdk1.5.0_07,如果安装时更改了默认路径,以实际安装路径为准。在JDK安装路径下应该能够找到bin、lib等目录。JAVA_HOME设置方法如图1.4所示。
图1.4 编辑系统变量JAVA_HOME对话框
PATH环境变量原来Windows里面就有,只需修改一下,使它指向JDK的bin路径。这样在DOS控制台下面编译、执行程序时就不需要再键入一大串路径了。PATH环境变量的设置方法如图1.5所示。保留原来PATH的内容,并在原有内容前加上“%JAVA_HOME%\bin;”,其中%JAVA_HOME%是指引用上一步设定好的环境变量JAVA_HOME的变量值。
3
图1.5 编辑系统变量PATH对话框
设置CLASSPATH环境变量。环境变量CLASSPATH告诉JAVA编译程序到什么地方搜索那些不是 JDK平台本身附带的类库,设置方法如图1.6所示。
CLASSPATH = .;%JAVA_HOME%\lib\tools.jar; %JAVA_HOME%\dt.jar;
图1.6 编辑系统变量CLASSPATH对话框
要注意最前面的".;",就是“句点分号”。设置后,JDK搜索类时将首先查找当前目录中的类文件。dt.jar是关于运行环境的类库,主要是swing的包;tools.jar是关于一些工具的类库。
设置好JAVA_HOME, PATH 和CLASSPATH环境变量后点击确定,关闭系统选项卡,完成JAVA环境配置。
3. 测试 JDK安装。
打开MS-DOS窗口,键入 java -version并按回车键,如图1.7所示,屏幕将打印出当前的JDK版本信息。
图1.7 JDK安装测试
4
实验1.4.2: (D)JAVA Application简单小程序
Java程序的多种类型: 服务器端Servlet小程序、Applet小程序、Application应用程序。
Servlet是运行在服务器端的小程序,在最后一章实验网络程序设计中会详细解释。Applet是嵌入到网页里完成某种特殊功能的小应用程序,由浏览器中的JAVA解释器负责解释执行。Application应用程序是独立运行在JAVA虚拟机上的应用程序。
在运行JAVA程序前, 所有的JAVA源文件(Source File)必须预先进行编译(Compile)。 对源文件的编译工作可以在MS-DOS窗口进行。步骤如下:
1. 确认Lab01文件目录已复制到本地磁盘。
实验中我们假设Lab01文件目录位于C盘根目录。 Lab01 文件目录中将包含本章实验所需的所有资料。
2. 打开MS-DOS窗口,如图1.8所示。
具体方法之一:Windows的开始 , 程序 , 附件 , 命令提示符。
图1.8 MS-DOS窗口
如果DOS窗口占据了整个电脑屏幕, 使用[Alt][Enter]改变DOS窗口大小。
3. 在MS-DOS的命令提示符下, 键入:
C:
cd \Lab01
命令的运行结果如图1.9所示。
图1.9 cd命令执行结果
4. 在C:\Lab01> 提示符后, 键入:
dir
dir命令将列出Lab01目录中的所有文件。在此Lab01目录中,包含了一些JAVA源文件, 即后缀为 .java 的文件。
5. 使用以下的命令编译JAVA源文件HelloWorld.java:
javac HelloWorld.java
5
运行HelloWorld.java:
java HelloWorld
程序在MS-DOS窗口显示:
C:\Lab01>
Hello World! This is an application!
6. HelloWorld.java源代码清单见程序清单1-13。
程序清单1-13:HelloWorld.java
public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World! This is an application!");
}
}
这个简单的Java程序包含了基本的代码块,本实验教程中的大多数程序都有类似的基本结构。下面对每行代码做一个简单的
。
public class HelloWorld
Java程序是由类(class)构成的。第1行代码定义一个类,它的类名叫HelloWorld(Java编程惯例要求类名的第一个字母为大写字母)。
public static void main(String[] args)
类(class)中包含方法(method)。第2行代码定义了一个main方法,对于一个应用程序来说main方法有且只有一个,程序的执行是从main方法的第一条语句开始的。圆括号中的“String args[ ]”是传递给main方法的参数,参数名为args。
System.out.println("Hello World! This is an application!");
main方法中的语句包含在一对花括号{ }之间。第3行代码是一个简单的输出语句。 实验1.4.3: (D)JAVA Applet简单小程序
下面是一个简单的Applet程序:
程序清单1-11:HelloWorldApplet.java
// HelloWorldApplet
import java.applet.*;
import java.awt.*;
public class HelloWorldApplet extends Applet {
public void paint(Graphics g) {
g.drawString("Hello World! This is an applet!\n", 20, 20);
6
} // paint
} // class HelloWorldApplet
程序中用import语句导入java.awt和java.applet包 ,使得该程序可能使用这些包中所定义的类。类名HelloWorldApplet后面的关键词extends指明HelloWorldApplet程序是Applet的子类,是一个Applet小程序。用extends指明它是Applet的子类。paint()方法中:
g.drawString("Hello World! This is an applet!\n", 20, 20);
实现了字符串“Hello World! This is an applet!”的输出,输出字符串的坐标为(20,20),其中坐标是用象素点来表示的。
这个程序没有实现main()方法 ,这是Applet与应用程序Application的区别之一。
1. 编译、运行Java Applet小程序:
把编译后的HelloWorldApplet嵌入到HTML文件中,在MS-DOS窗口用小程序查看器appletviewer运行或者在支持Java的浏览器上运行。具体的步骤如下:
首先,正确编译HelloWorldApplet.java程序得到相应的字节码文件HelloWorldApplet.class。
然后,编写ViewHelloWorldApplet.html文件,把“HelloWorldApplet.class”嵌入到html文件代码中。ViewHelloWorldApplet.html源代码见程序清单1-12。
程序清单1-12:ViewHelloWorldApplet.html
HelloWorld Applet
最后,在MS-DOS窗口执行:
C:\Lab01>appletviewer ViewHelloWorldApplet.html
程序的显示结果如图1.10
7
图1.10 用小程序查看器appletviewer查看HelloWorldApplet
如果执行appletviewer出现下面的警告:
警告:不能读取 AppletViewer 的属性文件: C:\Documents and Settings\Administrator
\.hotjava\properties 使用默认值。
这是由于applet编程的限制很多,所以也经常被称作关在“沙箱”里。运行Applet需要Java的运行时安全系统授权。一个简单的解决方法:
打开MS-DOS命令提示窗口,输入PolicyTool并按Enter会弹出一个类似图1.17的对话框,点击添加规则项目 , 添加权限 , 许可下拉菜单 , 选择 All Permission , 确认 , 完成。从文件菜单中选择另存为,在C:\Documents and Settings\Administrator(当前操作系统用户名)\中保存.java.policy文件(不同的操作系统可能有所不同,根据情况而定。例如图1.11中弹出的提示说明.java.policy文件要保存在C:\Documents and Settings\sl\路径下。)
图1.11 PolicyTool对话框
成功保存规则文件后,重新执行appletviewer。
用浏览器(IE或FireFox)打开ViewHelloWorldApplet.html,显示结果如图1.12所示。
图1.12用IE5浏览器查看HelloWorldApplet
2. 比较HelloWorld.java和HelloWorldApplet.java
8
写下Applet与Application两类Java程序的区别:
1. applet没有实现main()方法 ,这是Applet与应用程序Application的区别。
________________________________________________________________________________
2. applet需要嵌入到HTML文件中。
________________________________________________________________________________
实验1.4.4: (I)编译和运行一个JAVA程序
1( 在MS-DOS下C:\Lab01>提示符后使用以下的命令编译JAVA源文件Add.java:
javac Add.java
记住, JAVA编程语言是大小写敏感的。Add.java和add.java为两个不同的JAVA源文件。如果在编译JAVA源文件时出现:"error: Can't reaC: YourFileName.java", 这常常意味着(1)忘记更改盘符,当前目录下没有此JAVA文件 (2) 文件名写错了。如果遇到这样的错误信息,请检查MS-DOS提示符,确定正确的目录地址;认真检查文件名的拼写特别是大小写,然后重新键入编译命令。
一旦JAVA源文件Add.java编译通过,在Lab01目录下将出现一个后缀为.class的文件Add.class。在MS-DOS的命令提示符下键入 dir 确认Lab01目录中包含这个新生成的文件。
后缀为 .java 的文件是JAVA源代码(Source Code)文件, 由程序员编写,易读易修改;而后缀为 .class 的文件是JAVA字节码(Byte Code)文件。 字节码接近(不完全等同)于机器语言。在JAVA程序运行前,JAVA源文件必须编译成相应的字节码文件。
2. 运行JAVA程序。在C:\Lab01> 提示符后,键入:
java Add
如果编译和运行此程序正确,,在MS-DOS窗口将显示输出: 8 + 9 = 17. 如图1.13所示
图1.13 Add.java程序执行结果
实验1.4.5: (I)使用Windows记事本编写JAVA源代码文件 1. 用记事本打开Lab01文件目录中的Add.java文件。
可以将电脑设置成总是使用记事本打开JAVA源文件。具体操作如下:选中后缀为.java的文件,右击鼠标,选择[打开方式],[选择程序],选中[记事本],勾选[始终使用该程序打开这些文件]。如图1.14所示。现在,只要双击任何后缀为.java的文件, 就可以在记事本中打开。
9
图1.14文件打开方式对话框
程序清单1-1:Add.java
// JAVA编程语言实验第一章
// Add.java
public class Add {
public static void main(String[] args) {
int num1, num2, sum;
num1 = 5;
num2 = 9;
sum = num1 + num2;
System.out.println(num1 + " + " + num2 + " = " + sum + ".");
} // method main
} // class Add
2. 一旦用记事本打开Add.java, 修改如下语句:
num1 = 8;
修改后:
num1 = 5;
除了将8变成5以外,不要对程序作任何修改。在记事本中保存修改后的文件, 具体操作: [文件] , [保存], 注意: 不是[另存为]。现在,在MS-DOS的命令提示符下重新编译和运行JAVA程序:
javac Add.java
java Add
如果操作正确,MS-DOS窗口显示:"5 + 9 = 14."
3. 一旦这个简单程序能够正确运行,接下来对源代码进行更多的修改,将两个整数相加改写成两个整数相乘。步骤如下:
10
(1) 在修改Add.java之前,创建一个此文件的副本。具体操作:在记事本中打开Add.java文件,选择[文件],[另存为],在弹出的对话框中填写Multi.java,然后保存。
(2) 打开Multi.java源文件,修改代码。一共有五处代码需要修改。
(3) 首先,修改类名:
public class Add {
修改后:
public class Multi {
注意,JAVA程序公共类的类名必须和文件名相同。
(4) 其次,修改语句:
sum = num1 + num2;
修改后:
sum = num1 * num2;
这里,将加号(+)变成乘号 (*)。JAVA语言和其他编程语言一样,乘法使用星号(*),而不是“x”。
被修改的这条语句称为赋值语句(Assignment Statement),其中的sum, num1 和num2被称为变量(Variable)。程序运行时,这些变量存储在计算机内存中。赋值语句由变量名,赋值符号(=)和表达式组成,赋值符号(=)将右边的值赋给左边的变量。
(5) 修改后的程序不再进行加法运算,而是进行乘法运算,变量名sum 不如product恰当。即使使用不恰当的变量名,程序也能正确运行,但不恰当的变量名可能会降低源代码的可读性,给其他程序员在修改程序时带来不便。
将源文件中所有的sum替换成product。在Add.java中,sum出现了三次,将它们一一修改。 (6) 修改输出语句:
System.out.println(num1 + " + " + num2 + " = " + sum + ".");
修改后:
System.out.println(num1 + " * " + num2 + " = " + product + ".");
将" + "替换成" * ",使屏幕的输出语句显示正确的算术运算符。注意不要改变其他的加号,另外的这些加号不是用于计算,而是用于连接不同的字符串生成输出语句。 (7) 最后,修改源文件顶部和结束部分的注释,
// Multi.java
// class Multi
注释指程序中的解释性文字,编译器将不对其编译,即注释不是程序的一部分。对代码进行编译时,注释部分会被编译器忽略。但书写良好的注释极为重要,注释能提供代码的相关信息,如源代码的版本,源代码中变量的意义,其中使用的算法等。遵循某种规范书写的注释,甚至可以用于编写JAVA文档。在JAVA编程中,注释行通常是以双斜线(//)开始的。 (8) 保存修改后的Multi.java文件。在MS-DOS的命令提示符下编译此JAVA程序:
javac Multi.java
成功编译源文件后,可运行程序:
java Multi
记住:每次对JAVA源文件进行修改,对修改后的程序进行测试,都遵循这样的次序:源代码修改,保存,编译,运行。
实验1.4.6: (I)带消息对话框的JAVA程序
1. 在C:\Lab01目录下,编译和运行JAVA程序:
11
javac AddDialog.java
java AddDialog
运行此JAVA程序,会跳出一个单独的对话窗口,如图1.12所示。选择[确定]按钮可重新返回MS-DOS窗口命令提示符。
图1.15 JOptionPane对话框
2. 在Lab01文件夹,双击AddDialog.java文件,用记事本打开源代码文件。
程序清单1-2:AddDialog.java
// Add.java
// 没有输入值但有弹出对话框的简单加法程序
import javax.swing.JOptionPane;
public class AddDialog {
public static void main(String[] args)
{
int number1, number2, sum;
number1 = 2;
number2 = 3;
sum = number1 + number2;
JOptionPane.showMessageDialog(null,
number1 + " + " + number2 +
" = " + sum + ".");
System.exit( 0 ); // 结束程序
} // method main
} // class AddDialog
AddDialog.java程序和Add.java程序非常类似,但有几个语句不同。下面就是显示对话框的语句:
JOptionPane.showMessageDialog(null, num1 + " + " + num2
+ " = " + sum + ".");
在AddDialog.java程序的顶部位置,多了这样的语句:
import javax.swing.JOptionPane;
import 是JAVA语法中的一个关键词(keyword), 用于引入JAVA类库(Class Libray)中特定的JAVA类或package包。此程序引入了java.swing.JOptionPane类,java.swing.JOptionPane 类帮助生成显示信息的标准对话框,如图1.15所示。
12
3. 对代码做如下修改:
// import javax.swing.JOptionPane;
在import语句前插入//, 成为一个注释语句。Java中可以采用三种注释方式:
(1) // 用于单行注释。注释从//开始,终止于行尾。
(2) /*...*/ 用于多行注释。注释从/*开始,到*/结束,且这种注释不能互相嵌套。
c注释。它以/**开始,到*/结束。这种注释主要是为支持JDK(3) /**...*/ 是Java所特有的do
工具javadoc而采用的。
注释不仅仅是对程序的解释,有时它对于程序的调试也非常有用。譬如说可以利用注释屏蔽一条语句以观察变化,发现问题和错误,如同正在进行的练习。
4. 保存和编译修改后的AddDialog.java源文件, 写下编译JAVA源文件时的错误信息:
AddDialog.java:15:找不到符号
符号:变量jOptionPane
位置:类AddDiaLog
JOptionPane.showMessageDialog(null,number1 + " + " + number2 + " = " + sum +
".");
1 错误
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
这段错误信息的意思是:编译器不理解JOptionPane是什么, 没有import语句
import javax.swing.JOptionPane;
编译器无法找到相关信息。
5. 将import语句前的 // 去掉,保存源文件后重新编译。保证源代码正确,继续完成下面的练习。 实验1.4.7: (I)简单的计算程序
1. 编译、运行Area.java程序。在MS-DOS窗口命令提示符下键入:
javac Area.java
成功编译后,运行该JAVA程序:
java Area
2. 用记事本打开Lab01文件夹中的Area.java源文件(假设Lab01文件夹放在C盘根目录下)。
程序清单1-3:Area.java
// Area.java
// 没有输入值的矩形面积计算
public class Area {
13
public static void main( String[] args )
{
float length, width, area;
length = 15.5f;
width = 22;
area = length * width;
System.out.println(
"长为" + length + " 和\n" +
"宽为" + width + " 的矩形面积是" + area + "." );
} // method main
} // class Area
其中计算长方形面积的语句:
area = length * width;
为赋值语句。语句中的area, length, 和 width 是变量(Variable)。变量在使用前必须预先声明(Declaration)。简单地理解,变量声明就是说明变量的数据类型,为变量分配相应的内存空间。语句:
float length, width, area;
声明了area, length, 和 width的数据类型为float(单精度浮点小数)。
比较Add.java源文件中的语句:
int num1, num2, sum;
int是JAVA语言的另一种基本数据类型。这一语句声明了 num1, num2, sum变量的数据类型为int 整型。int 声明的变量可以是正整数,可以是负整数,也可以是零。JAVA语言标准规定 int 的取值范围为 –2,147,483,648 ~ 2,147,483,647。 int类型数据的存储占4个字节(32位)。
3. 下面,创建一个新的JAVA程序来计算长方体的体积。
将Area.java源文件另存为Volume.java, 对Volume.java源文件做如下修改:
(1) 首先,修改类名:
public class Volume {
(2) 改变注释
// Caluclates volume of a rectangular box.
(3) 修改代码行:
float length, width, area;
修改后:
float length, width, height, volume;
此程序不再需要area变量,另外增加了两个相应的变量height和volume。注意变量名的书
写正确,通常变量名的组成字母都要小写。确定逗号和分号书写正确,逗号用于分隔不同的变量,
分号写在一个语句的末尾。
这一代码行进行了变量声明(Variable Declaration)。JAVA程序中,使用任何变量前,必
须事先予以声明。
(4) 为变量height赋值,在语句:
14
width = 22;
后插入赋值语句(Assignment Statement):
height = 55;
(5) 改变赋值语句进行正确的体积运算:
area = length * width;
修改后:
volume = length * width * height;
JAVA程序现在包含这样4个赋值语句:
length = 15.5f;
width = 22;
height = 55;
volume = length * width * height;
重点检查一下标点符号, 并确定所有的变量为小写字母。
(6) 修改输出语句:
System.out.println(
"长为" + length + " 和\n" +
"宽为" + width + " 的矩形面积是" + area + "." );
修改后:
System.out.println(
"长为" + length + " ,\n" +
"宽为" + width + ",和高为"+height+"\n"+" 的长方体体积是" +
volume + "." );
(7) 最后,保存文件,进行编译。如果编译出错,再一次检查拼写、大小写和标点符号。编译器
的错误信息中会指明出错的行号。假如,13行“height”拼写成“hight”错误,出错信息
如下:
Volume.java:13: 找不到符号
符号:变量 hight
位置:类Volume
volume = length * width * hight;
^
1 错误
错误信息当然并不都是这样清楚地指明错误的类型和位置,有些错误信息难以理解。这些难
以理解的信息可能仅仅是由于某个分号的缺失。认真检查错误信息提示的代码行,以及邻近的代
码行。
如果得到许多“Undefined variable”错误信息,请仔细检查指定行变量名的拼写。
更正错误后,保存和重新编译JAVA程序。程序编译正确后,运行程序,观察运行结果是否
正确。
(8) 观察语句中15.5后的f:
length = 15.5f;
试着删除 f, 语句修改后:
length = 15.5;
保存、编译源文件,写下错误信息:
15
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
JAVA浮点小数分为单精度和双精度, 分别用float和double表示。float类型数据的存储
占4个字节(32位),double类型数据的存储占8个字节(64位)。
程序中的15.5,22 和55 被称为数值文字(Numeric Literals)。其中包含小数点的数值文
字,编译器将其解释为double类型数据,而不是float类型数据;除非在包含小数点的数值文
字后面加上f或F,如15.5f。
所以,15.5f去掉f 后,编译器将15.5理解为double类型,将double类型的15.5赋值给
float类型的length就会导致程序不能编译。这是由于double的精度比float高,将一个高精
度的double赋值给一个低精度的float时需要进行强制类型转换,反之则不需要。
解决这一问题的三种方法:
方法一:在15.5后面加上字母f。
length = 15.5f;
方法二:将double类型的15.5强制类型转换成float, 当然这会损失数据的精度。
length = (float)15.5;
方法三:将length变量声明成double类型。这种方法需要占用更多的内存,计算结果应该
会更精确。对于目前这个极为简单的程序而言,有点大材小用。
程序中其他的数值文字,如22、55, 属于int类型。int类型的22赋值给float类型的width
时,可执行自动的类型转换,即将int类自动转换成float类。
(9) 编辑Volume.java源文件,使其能正确编译和运行。将源代码保存在Lab01目录下。 实验1.4.8: (I)JAVA SDK错误信息指南
练习要求把正确的代码改为错误的代码,并观察代码错误时,编译器显示的错误信息。理解这些错误信息的含义。
1. 用记事本打开Area.java源文件,保存为Syntax.java。不要对Syntax.java文件作任何修改,不要修改公有类的类名。在MS-DOS的命令提示符下键入:
16
javac Syntax.java
写下MS-DOS窗口的错误信息:
______
_________________________________________________________
_______________________________________________________________
_______________________________________________________________
现在,修改公有类类名:
public class Area {
修改后:
public class Syntax {
保存文件,进行编译。如果程序还是不能正确编译,注意检查文件名、类名、javac Syntax.java
命令的拼写和大小写是否正确。确认MS-DOS提示符显示正确盘符和路径。(如果对此有所疑问,请查
阅DOS指南。)
文件正确编译后,我们再继续介绍其他语法错误。一次只观察一个错误。
2. 观察Syntax.java源文件中的注释行:
// Caluclates area of a rectangle
删除此行中的双斜线,对编译器来讲,此行不再对编译器是透明的。保存、编译文件。写下MS-DOS
窗口的错误信息:
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
Java编译器所能理解的语言只能是符合JAVA语法规则的编程语言,而不是人类的自然语言。
写回双斜线,注释对编译器来讲又是透明的了。保存和编译源文件,确定程序没有任何错误。
3. 观察Syntax.java源文件中的代码行:
17
public class Syntax {
public static void main( String[] args ){
……
} // method main
} // class Syntax
代码中有两对花括号{}。JAVA语法要求,左括号和右括号必须一一对应。
-DOS窗口的错误信息: 删除其中一个右括号,保存源代码并编译,写下MS
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
写回删除的花括号,保存和编译源文件,确定程序没有任何错误。
4. 注释掉 Syntax.java源文件中的代码行:
// float length, width, area;
保存和编译源文件。这一次编译器给出的错误信息有很多项。不用把所有的错误信息都写下来,
只需要写下最后的几行:
_______________________________________________________________
18
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
注释掉的代码行是变量声明语句,声明变量length, width和area为float类型。没有这一行,
编译器无法识别变量名length, width和area。JAVA中使用的所有变量都必须被声明为某一特定的
数据类型,如int (整型)、float (单精度浮点小数)、double (双精度浮点小数)。否则,将被编译
器认定为“undefined未定义的”。
删除双斜线,保存和编译源文件,确定程序没有任何错误。
5. 删除 Syntax.java源文件中代码行末尾的分号:
float length, width, area;
修改后:
float length, width, area
保存源代码并编译,写下MS-DOS窗口的错误信息:
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
JAVA程序的几乎每一行,包括所有的变量声明语句,所有的赋值语句,都必须以分号(;)结尾。
写回删除分号,保存和编译源文件,确定程序没有任何错误。
6. 有时,分号的缺失产生的错误信息不一定能反映出错误的出处。删除 Syntax.java源文件中代码
行末尾的分号:
length = 15.5f;
修改后:
length = 15.5f
保存源代码并编译,写下MS-DOS窗口的错误信息:
19
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
7. 前面已经提到,JAVA程序的几乎每一行,包括所有的变量声明语句,所有的赋值语句,都必须以
分号结尾。当然也有例外,如类的头部和main方法的头部。
public class Syntax
public static void main(String[] args)
在代码行末尾加上分号:
public static void main(String[] args)
修改后:
public static void main(String[] args);
保存源代码并编译,写下MS-DOS窗口的错误信息:
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
不用担心错误信息的意思,只需要理解这里的分号将main方法的头部和main方法的主体划分开,
导致了编译的错误。main方法的主体是指main方法头部后的左花括号和对应的右花括号之间的代码
段。 移走不恰当的分号,保存和编译源文件,确定程序没有任何错误。
实验1.4.9: (W)命令行参数
使用命令行参数可以编写更为灵活的程序。
1. 编译AverageOf3Num.java程序,在MS-DOS命令提示符中键入如下命令运行程序:
java AverageOf3 100 203 630
使用三个其他的整数再次尝试运行。如
java AverageOf3 45 54 93
在以上两例中,每次程序运行都显示了一个整数,它是键入的三个数字的平均数,程序两次运行
结果如
图1.16所示。
20
图1.16 AverageOf3Num.java程序运行结果
2. 用记事本打开AverageOf3Num.java源文件。
程序清单1-4:AverageOf3Num.java
// AverageOf3Num.java
public class AverageOf3Num {
public static void main(String[] args)
{
int number1, number2, number3;
int average;
number1 = Integer.parseInt(args[0]);
number2 = Integer.parseInt(args[1]);
number3 = Integer.parseInt(args[2]);
average = (number1 + number2 + number3) / 3;
System.out.println("数字 " + number1 +
", " + number2 + ", 和 " +
number3 + " 的平均数是 " + average + ".");
} // method main
} // class AverageOf3Num
注意其中的赋值语句:
firstNumber = Integer.parseInt(args[0]);
secondNumber = Integer.parseInt(args[1]);
thirdNumber = Integer.parseInt(args[2]); 这些赋值语句和前面讲过的赋值语句有所不同,不是简单地将预定的数值赋值给变量。
3. 为了理解上面这些赋值语句,参看程序Hello.java
程序清单1-5:Hello.java
public class Hello {
public static void main(String[] args) {
String text;
text = "Hello!";
21
System.out.println(text);
} // method main
} // class Hello
编译、运行Hello.java程序将在MS-DOS窗口输出:
Hello!
声明语句将变量 text 声明为字符串类型(String)。字符串就是一串字符,字符串类型的变量引用存储在计算机里的一串字符。这个字符串就是字符串变量的值。实际上,字符串中的字符在计算机中也是以数字形式存储的。计算机中所有的值,包括数值和字符,都以二进制形式存储在计算机中。Java中,每个字符以Unicode(统一字符编码标准)编码,用16个位(bit)表示一个字符。
4. 现在编译CommandDemo1.java文件, 并键入
java CommandDemo1 firstname lastname
运行程序。用练习者实际的名和姓替换掉命令行中的firstname、lastname,观察输出结果。然后用记事本打开Lab01目录下的CommandDemo1.java文件。
程序清单1-6:CommandDemo1.java
// CommandDemo1.java
// 演示命令行参数,期望用户键入他实际的名字:
//
// java CommandDemo1 firstname middlename lastname
public class CommandDemo1 {
public static void main(String[] args)
{
String name;
name = args[0] + " " + args[1] ;
System.out.println("Hello, " + name + ".");
} // method main
} // class CommandDemo1
代码中,args[0]和args[1]是字符串类型的变量。它们是一系列特殊的字符串变量,由Java虚拟机自动赋值。通常它们被称为命令行参数(Command Line Argument)。在MS-DOS命令提示符后键入如下命令运行带有命令行参数的JAVA程序:
java CommandDemo1 firstname lastname
其中,命令行参数的值等于类名CommandDemo1右侧键入的字符串。此处args[0]是类名右侧第一个字符串firstname,args[1]是类名右侧第二个字符串lastname,以此类推。MS-DOS命令提示符中键入命令行参数时,必须以空格将它们分开。
args这样的一组序列称为数组。数组是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和下标来唯一地确定数组中的元素。后面的实验里,我们会具体讨论数组这一话题。目前实验中只会用到JVM(Java Virtual Machine,JAVA虚拟机)自动创建的命令行参数数组。
在CommandDemo1.java程序中,字符串变量 name 的赋值是通过连接不同其他字符串,形成单个长字符串来实现的。请注意,符号“,”除了作加法之外,也用于字符串连接。如果加号两边的值
22
是数字(比如int, float类),它用于加法;否则,如果加号任何一边的表达式是字符串,它就用于字符串连接。
5. 再次观察AverageOf3Num.java,程序显然使用了命令行参数。
当第一次运行这个程序时,命令行参数的值就是字符串“100”,“203”,“630”。注意,字符串值“100”、“203”、“630”与整数值100、203、630的不同。字符串和整数在计算机里的存储方式彼此
”包括两个字符,每个都是以16位不同,比如说,整数以单个32位二进制形式存储,而字符串“30
二进制形式存储的。
所以,为了以整数形式使用命令行参数,必须将它们从字符串转换为整数。具体方法是调用Integer.parseInt。如AverageOf3Num.java文件中的语句:
firstNumber = Integer.parseInt(args[0]);
Integer.parseInt将命令行参数args[0]的值(一个字符串)转化成整数,再将整数值赋值给变量firstNumber。
6. 观察AverageOf3Num.java文件中的另一条语句:
average = (number1 + number2 + number3) / 3;
在代数中,这里的圆括号用来确保在除法之前做加法。没有圆括号,根据算术运算的优先级,以上的表达式将是先将number3除以3,再做加法运算。
7. 运行不带命令行参数的AverageOf3Num.java程序:
java AverageOf3Num
然后,加两条命令行参数再运行此程序,如:
java AverageOf3Num 23 55
以上两例的运行结果都是输出错误信息,如图1.14所示。
图1.17运行带有命令行参数的JAVA程序
这些信息除了对经验丰富的程序员有意义之外,对一般用户来说没有多大意义。应该让程序输出用户友好的信息,譬如告诉使用者怎样运行程序。
8. 创建MyAverageOf3Num.java程序,输出用户友好的信息。程序运行结果如图1.15所示。
图1.18 MyAverageOf3Num.java程序运行结果
将AverageOf3Num.java文件当作副本文件MyAverageOf3Num.java保存。改动
23
MyAverageOf3Num.java源文件的注释、程序类名等,使修改后的MyAverageOf3Num.java程序,在MS-DOS命令行输出以下信息:
此程序将计算键入的三个命令行参数的平均数.
运行程序,在MS-DOS提示符下键入:
java MyAverageOf3 int1 int2 int3
其中, int1、int2、int3使用整数值。
要求程序调用System.out.print 和System.out.println输出以上结果。System.out.println输出字符串之后,输出的光标移至下一行,使下一个输出字符串在下一行显示出来。而System.out.print并未将光标移至下一行,结果就是:下一个输出的字符串将会在同一行显示。例如,以上输出信息可由以下输出语句组得出:
System.out.print("此程序将计算键入的三个命令行参数 ");
System.out.println("的平均数:");
使用输出语句组的优点在于可避免一行语句过长,不便于阅读。
完成代码编写后,编译程序。如果程序中包含语法错误,程序将无法编译。在这种情况下,必须进行必要的代码修改,直到正确编译为止。然后,分别在无命令行参数、有命令行参数或命令行参数不完整的情况下运行此程序。
实验1.4.11: (W)条件语句
MyAverageOf3Num程序中没能摆脱那些难懂的“异常”错误信息。即使当用户已经知道程序需要输入三个命令行参数,程序也会每次都显示出指导信息。如果程序只在需要时出现这些指导信息就更好了。
1. 编译Lab01目录下的IntDivision1.java源文件:
javac IntDivision1.java
首先, 使用无命令行参数运行程序:
java IntDivision1
然后,根据程序输出提示运行程序。
2. 打开IntDivision1.java源文件。
程序清单1-7:IntDivision1.java
public class IntDivision1 {
public static void main(String[] args) {
if ( args.length < 2 ) {
System.out.print("此程序将显示 ");
System.out.println("作为命令行参数输入的两个整数");
System.out.println("相除的商和余数");
System.out.println("运行此程序,键入:");
System.out.println(" java IntDivision1 int1 int2");
System.out.print("用整数值替代 ");
System.out.println("int1和int2.");
} // if
24
int dividend = Integer.parseInt(args[0]);
int divisor = Integer.parseInt(args[1]);
int quotient = dividend / divisor;
int remainder = dividend % divisor;
System.out.println(dividend + " divided by " +
divisor + " is " +
quotient + " with remainder " +
remainder + ".");
} // method main
} // class IntDivision1
输出的指导信息语句是被附在“if”结构中的。这段语句只有命令行参数少于两个时才被执行,被称之为条件语句。args.length表达式可得到用户键入的命令行参数的个数。如果用户键入两个命令行参数,则args.length值为2;如果用户没有键入命令行参数,则args.length的值为0。 “if”关键字后面,圆括号内的表达式
args.length < 2
表示:如果命令行参数个数小于2,则args.length < 2表达式的值为真(true)。关键字“if”后、圆括号内的表达式被称为条件表达式。这段输出语句只有在args.length < 2这个条件表达式为真时,才被执行。
条件语句是程序设计中最常用的语句,用它来选择程序的执行流程。在后面的实验中会讲解更多类型的条件语句。
Java语言规范中的编码标准部分规定,if语句的换行通常使用缩进排版(Indentation)。4个空格常被作为缩进排版的一个单位。缩进排版不会影响JAVA程序的编译和运行,而恰当的缩进排版可增加程序的可读性。有经验的程序员知道,程序的可读性是极为重要的,程序的可读性就是效率,程序的可读性是仅次于正确性的一个重要指标。
3. 修改MyAverageOf3Num.java文件。
要求程序运行时,只有当用户键入少于三个命令行参数时才输出指导信息。注意编写条件语句时缩进排版。改动后,再次编译MyAverageOf3Num.java,运行程序,验证程序的正确性。
目前使用非命令行参数运行程序依然会显示出异常错误信息。为了消除不友好信息,在if代码段的最后一行,即右括号}前插入语句:
System.exit(0);
System.exit(0) 终止当前正在运行的 Java 虚拟机,简单的讲就是将系统退出,使后续的代码都不被执行。
调试运行程序。在用户键入少于三个命令行参数时,程序只显示指导信息;在用户键入至少三个命令行参数时,程序运行正确。.
实验1.4.12: (I)整型与浮点型除法
Java的基本数学运算符和大多数程序语言一样,包括:加(+)、减(-)、乘(*)、除(/)、模(%,用来取得整数相除后的余数)等。
25
除法运算中,求整型商数的代码片段:
int quotient = dividend / divisor;
求余数的代码片段:
int remainder = dividend % divisor;
符号/表示除法运算符,符号,表示模运算符,即整数相除后的余数,简写为mod。
IntDivision1.java源程序(程序清单1-7)中,
int dividend = Integer.parseInt(args[0]);
变量的声明和变量赋初值在同一条语句完成,而在之前的例子中,变量声明和变量赋初值是由两条语句完成的。两种方式的变量声明都是许可的,只要:(1)每个变量只声明了一次;(2)变量在赋初值前已经声明。
使用命令行参数运行MyAverageOf3Num.java程序:
java MyAverageOf3Num 4 5 5
程序输出平均值为4,但这并不是真正的平均值,它是整数除法的结果。要得到更准确的平均数,使用浮点除法更合适。浮点除法得到的是一个非整数的商数。
修改MyAverageOf3Num.java源程序。声明变量average的数据类型为float,然后再次使用命令行参数运行这个程序。写下程序输出:
Averagre=4.0
__________________________________________________
尽管变量 average现在是float类型,并且它的值是以浮点数形式输出;然而程序目前并未将除法转换为浮点值除法。除法运算符在其两边表达式都为整数时,做整数除法。当其任何一边为浮点值时,做浮点值除法。修改MyAverageOf3Num.java源代码为:
average = (float) (number1 + number2 + number3) / 3;
另一种方法编码方式:
average = (number1 + number2 + number3) / 3.0f;
修改、编译、重新运行MyAverageOf3Num.java程序,得到更加精确的算术平均数。 实验1.4.13: (D)转义字符
JAVA中的字符数据类型(char)不是8位ASCII码字符集,而是Unicode字符集。JAVA中可以用\u的形式来表示字符,如 \u2122表示商标符号(?),其值范围为 \u0000 到 \uFFFF。还可以使用转义字符(Escape Sequences)表示特殊字符。
表1-1转义字符表
转义字符 显示
回退符 \b
制表符 \t
换行 \n
双引号 \"
单引号 \'
反斜杠 \\
26
编译, 运行应用程序EscapeSequences.java。在记事本打开。
程序清单1-8:EscapeSequences.java
public class EscapeSequences {
public static void main(String[] args) {
System.out.println("Beep!\u0007");
System.out.println("1.\n2.\n3.\n4.");
System.out.println("Couldn\'t find \"Mary\" in
A:\\STUDENTS.TXT");
} // method main
} // class EscapeSequences
注意在System.out.println()的语句中的字符和程序运行后显示在输出屏幕上的字符有所不同。例如:
System.out.println("1.\n2.\n3.\n4."); 这一输出语句不会输出 “\n”字符串, 而是将 \n 解释为换行。下面的这个语句在JAVA中可能不会实现预想的输出换行:
System.out.println("1.
2.
3.
4.");
在JAVA程序中,字符串常量(String Literal)是由双引号引起来的一系列字符。此时,回车换行可以使用Sysem.out.println语句。例如:
System.out.println("1.");
System.out.println("2.");
System.out.println("3.");
System.out.println("4.");
如果只用一个System.out.println()输出语句,就需要使用“\n”转义字符。如程序中的语句:
System.out.println("1.\n2.\n3.\n4.");
表1-1列出了其他的一些转义字符。
将程序中的语句:
System.out.println("Couldn\'t find \"Mary\" in
A:\\STUDENTS.TXT");
与MS-DOS窗口的实际输出结果向比较,\" 用于输出引号,\\用于输出反斜杠。试着删除反斜杠,保存编译修改后的文件,观察其中的变化。
运行EscapeSequences.java程序时发出的BB声是由转义字符 \u0007 实现的,\u0007被称为响铃符。见Escape Sequences1.java源文件的第一行输出语句。
字符(characters)是以二进制编码的方式存储在计算机中的。字符包括字母,数字,标点符号和控制符,如水平制表(tab)、硬回车(carriage return)、退格(backspace)、换行(newline)。尽管控制符都是不可打印出的字符,但它们和其他字符一样以二进制的方式存储在计算机中内存中。
27
实验1.4.14: (I)练习使用转义字符
1. 编译,运行PracticeEscape.java 程序, 观察出现的错误信息。
程序清单1-9:PracticeEscape.java
public class PracticeEscape {
public static void main(String[] args) {
System.out.println("Don't be fooled by misleading syntax");
System.out.println("error messages about ")" and ";".");
System.out.println("The compiler doesn't know what you're");
System.out.println("trying to do.");
} // method main
} // class PracticeEscape
在程序中插入转义字符,使程序能正确运行,并在MS-DOS窗口输出:
Don't be fooled by misleading syntax
error messages about ")" and ";".
The compiler doesn't know what you're
trying to do.
2. 编译、运行另一个JAVA程序:EscapeSequences2.java。
程序清单1-10:EscapeSequences2.java
public class EscapeSequences2 {
public static void main(String[] args) {
System.out.println("Beep! \u0007");
System.out.println("Displaying single quotes: " +
"\'A\'");
System.out.println("Displaying double quotes: " +
"\"string\"");
System.out.println("Displaying a backslash: \\");
System.out.println("Text separated\t\tby two tabs.");
System.out.println("Here is double\n\nspaced text.");
System.out.println("The next line demonstrates '\\r':");
System.out.println("**********\r#####");
} // method main
} // class EscapeSequences2
比较源文件中的System.out.println()语句和程序运行后的输出。注意观察硬回车(\r)和换行(\n)
的区别,写下观察结果:
28
__________________________________________________
__________________________________________________
实验1.4.15: (I)键盘输入
1. 编译、运行KeyboardInputExample.java程序。
程序提示用户从键盘读入一个整数,计算这个整数的绝对值。比较实验1.4.9从命令行输入参数,这种从键盘输入数据的方式要稍微复杂一些,初学者不必完全理解这些代码,只要把相关的代码复制到程序中就行了。
程序清单1-9:KeyboardInputExample
import java.io.*;
public class KeyboardInputExample {
public static void main(String[] argv) throws IOException {
// 从键盘输入数据
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("输入一个整数:");
String temp = br.readLine();
int x = Integer.parseInt(temp);
if ( x < 0 ) {
x = 0-x;
}
System.out.println("这个整数的绝对值是: " + x);
} // main
} // KeyboardInputExample
29
从键盘获取数据,实现的代码如下:
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("输入一个整数:");
String temp = br.readLine();
这里的System.out.println语句很有必要,程序运行中,当用户看到这样的提示信息时,就知道需要输入一些数据。输入数据后按回车键结束输入,程序使用输入数据继续执行。
输入数据存放到字符串变量temp中,所以,如果不想把输入的数据当成字符串来使用,就需要将它转换成正确的类型。Java提供了变量类型转换的方法,如下所示的7个例子。
x = Double.parseDouble(temp); //将string类型的temp转换成double类型的x
y = Float.parseFloat(temp); //将string类型的temp转换成float类型的y
i = Long.parseLong(temp); //将string类型的temp转换成long类型的i
j = Integer.parseInt(temp); //将string类型的temp转换成int类型的j
k = Short.parseShort(temp); //将string类型的temp转换成short类型的k
m = Byte.parseByte(temp); //将string类型的temp转换成byte类型的m
a = Boolean.valueOf(temp).booleanValue(); //将string类型的temp转换成boolean类型的a
需要注意的是,x、y等变量必须首先被声明为它们各自的变量类型。在后面的实验中,我们将会用到这种数据输入方法。
源代码中的import语句:
import java.io.*;
告诉编译器程序将用到Java类库的java.io包。
Java的异常处理机制对错误进行处理。获取键盘输入数据可能会产生IOException(输入输出异常)。程序处理这种异常的简单作法就是声明main方法抛出了IOException异常。
public static void main(String[] argv) throws IOException
在以后的课程中,会更好地理解这些概念。
2. 编写MyKeyboardInput.java程序,程序提示用户从键盘输入一个小数,并计算这个小数的绝对值,
输出到MS-DOS窗口(提示:小数的变量类型为double)。
30