《Java语言程序设计基础教程》
上机实验指导手册
1
实验一 Java环境演练
【目的】
①安装并配置Java运行开发环境;
②掌握开发Java应用程序的3个步骤:编写源文件、编译源文件和运行应用程序; ③掌握开发Java Applet程序的3个步骤:编写源文件、编译源文件和运行Java Applet程序;
④学习同时编译多个Java源文件。
【内容】
1.一个简单的应用程序
? 实验要求:
编写一个简单的Java应用程序,该程序在命令行窗口输出两行文字:“你好,很高兴学习Java”和“We are students”。
? 程序运行效果示例:
程序运行效果如下图所示: ? 程序模板: Hello.java
public class Hello
{
public static void main (String args[ ])
{
【代码1】 //命令行窗口输出"你好,很高兴学习Java"
A a=new A();
a.fA();
}
}
class A
{
void fA()
{
【代码2】 //命令行窗口输出"We are students"
}
}
? 实验后的练习:
1.编译器怎样提示丢失大括号的错误?
2.编译器怎样提示语句丢失分号的错误?
3.编译器怎样提示将System写成system这一错误?
4.编译器怎样提示将String写成string这一错误?
2.一个简单的Java Applet程序
? 实验要求:
编写一个简单的Java Applet程序,并在Java Applet中写两行文字:“这是一个Java Applet程序”和“我改变了字体”。
? 程序运行效果示例:
2
程序运行效果如下图所示:
? 程序模板:
FirstApplet.java
import java.applet.*;
import java.awt.*;
public class FirstApplet extends Applet
{
public void paint(Graphics g)
{
g.setColor(Color.blue);
【代码1】//在Java Applet中绘制一行文字:“这是一个Java Applet 程
序”
g.setColor(Color.red);
g.setFont(new Font("宋体",Font.BOLD,36));
【代码2】//在Java Applet中绘制一行文字:“我改变了字体”
}
}
? 实验后的练习:
5.程序中的主类如果不用public修饰,编译能通过吗?
6.程序中的主类如果不用public修饰,程序能正确运行吗?
7.程序将paint方法误写成Paint,编译能通过么?
8.程序将paint方法误写成Paint,运行时能看到有关的输出信息吗?
3.联合编译
? 实验要求:
编写4个源文件:Hello.java、A.java、B.java和C.java,每个源文件只有一个类,Hello.java是一个应用程序(含有main方法),使用了A、B和C类。将4个源文件保存到同一目录中,例如:C:\100,然后编译Hello.java。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
模板1:Hello.java
public class MainClass
{
public static void main (String args[ ])
{
【代码1】 //命令行窗口输出"你好,只需编译我"
A a=new A();
a.fA();
B b=new B();
b.fB();
}
3
}
模板2 :A.java
public class A
{
void fA()
{
【代码2】 //命令行窗口输出"I am A"
}
}
模板3 :B.java
public class B
{
void fB()
{
【代码3】 //命令行窗口输出"I am B"
}
}
模板4 :C.java
public class C
{
void fC()
{
【代码4】 //命令行窗口输出"I am C"
}
}
? 实验后的练习:
9.将Hello.java编译通过后,不断修改A.java源文件中的代码,比如,在命令
行窗口输出“我是A类”或“我被修改了”。要求每次修改A.java源文件后,
单独编译A.java,然后直接运行应用程序Hello。
10. 如果需要编译某个目录下的全部Java源文件,比如C:\1000目录,可以使
用如下命令:c:\1000\javac *.java
【结果】
将本次上机实验结果按照以上内容依次填写实验目标、过程、结果。
【注意事项】
① 实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
② 报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
4
实验二 Java基本数据类型与控制语句
【目的】
① 掌握char型数据和int型数据之间的相互转换,同时了解unicode字符表; ② 掌握使用if…else if多分支语句;
③ 使用if…else分支和while循环语句解决问题。
【内容】
1.输出希腊字母表。
? 实验要求:
编写一个Java应用程序,该程序在命令行窗口输出希腊字母表。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
GreekAlphabet.java
public class GreekAlphabet
{
public static void main (String args[ ])
{
int startPosition=0,endPosition=0;
char cStart='α',cEnd='ω';
【代码1】 //cStart做int型转换据运算,并将结果赋值给startPosition
【代码2】 //cEnd做int型转换运算,并将结果赋值给endPosition System.out.println("希腊字母\'α\'在unicode表中的顺序位置:"+(int)c);
System.out.println("希腊字母表:");
for(int i=startPosition;i<=endPosition;i++)
{
char c='\0';
【代码3】 //i做char型转换运算,并将结果赋值给c
System.out.print(" "+c);
if((i-startPosition+1)%10==0)
System.out.println("");
}
}
}
? 实验后的练习:
1. 将一个double型数据直接赋值给float型变量,程序编译时提示怎样的错
误?
2. 在应用程序的main方法中增加语句:
float x=0.618;
程序能编译通过么?
3. 在应用程序的main方法中增加语句:
byte y=128;
5
程序能编译通过么?
4. 在应用程序的main方法中增加语句:
int z=(byte)128;
程序输出变量z的值是多少?
2.回文数。
? 实验要求:
编写一个Java应用程序。用户从键盘输入一个1—9999之间的数,程序将判断这个数是几位数,并判断这个数是否是回文数。回文数是指将该数含有的数字逆序排列后得到的数和原数相同,例如12121、3223都是回文数。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
Number.java
import javax.swing.JOptionPane;
public class Number
{
public static void main(String args[])
{
int number=0,d5,d4,d3,d2,d1;
String str=JOptionPane.showInputDialog("输入一个1至99999之间的数");
number=Integer.parseInt(str);
if(【代码1】) //判断number在1至99999之间的条件
{
【代码2】 //计算number的最高位(万位)d5
【代码3】 //计算number的千位d4
【代码4】 //计算number的百位d3
d2=number%100/10;
d1=number%10;
if(【代码5】) //判断number是5位数的条件
{
System.out.println(number+"是5位数");
if(【代码6】) //判断number是回文数的条件
{
System.out.println(number+"是回文数");
}
else
{
System.out.println(number+"不是回文数");
}
}
else if(【代码7】) //判断number是4位数的条件
{
6
System.out.println(number+"是4位数");
if(【代码8】) //判断number是回文数的条件码 {
System.out.println(number+"是回文数"); }
else
{
System.out.println(number+"不是回文数"); }
}
else if(【代码9】) //判断number是3位数的条件 {
System.out.println(number+"是3位数");
if(【代码10】) //判断number是回文数的条件 {
System.out.println(number+"是回文数"); }
else
{
System.out.println(number+"不是回文数"); }
}
else if(d2!=0)
{
System.out.println(number+"是2位数");
if(d1==d2)
{
System.out.println(number+"是回文数"); }
else
{
System.out.println(number+"不是回文数"); }
}
else if(d1!=0)
{
System.out.println(number+"是1位数");
System.out.println(number+"是回文数"); }
}
else
{
System.out.printf("\n%d不在1至99999之间",number); }
7
}
}
? 实验后的练习:
1. 程序运行时,用户从键盘输入2332,程序提示怎样的信息?
2. 程序运行时,用户从键盘输入654321,程序提示怎样的信息?
3. 程序运行时,用户从键盘输入33321,程序提示怎样的信息?
3.猜数字游戏。
? 实验要求:
编写一个Java应用程序,实现下列功能:
1) 程序随机分配给客户一个1—100之间的整数
2) 用户在输入对话框中输入自己的猜测
3) 程序返回提示信息,提示信息分别是:“猜大了”、“猜小了”和“猜对
了”。
4) 用户可根据提示信息再次输入猜测,直到提示信息是“猜对了”。 ? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
GuessNumber.java
import javax.swing.JOptionPane;
public class GuessNumber
{
public static void main (String args[ ])
{
System.out.println("给你一个1至100之间的整数,请猜测这个数"); int realNumber=(int)(Math.random()*100)+1;
int yourGuess=0;
String str=JOptionPane.showInputDialog("输入您的猜测:");
yourGuess=Integer.parseInt(str);
while(【代码1】) //循环条件
{
if(【代码2】) //条件代码
{
str=JOptionPane.showInputDialog("猜大了,再输入你的猜测:"); yourGuess=Integer.parseInt(str);
}
else if(【代码3】) //条件代码
{
str=JOptionPane.showInputDialog("猜小了,再输入你的猜测:"); yourGuess=Integer.parseInt(str);
}
}
System.out.println("猜对了!");
}
8
}
? 实验后的练习:
1. 用“yourGuess>realNumber”替换【代码1】,可以么?
2. 语句:“System.out.println(“猜对了!”);”为何要放在while循环语句之后?放在while语句的循环体中合理吗?
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
9
实验三 类与对象、继承
【目的】
①使用类来封装对象的属性和功能;
②掌握类变量与实例变量,以及类方法与实例方法的区别;
③掌握使用package和import语句。
④巩固以下概念:
子类的继承性
子类对象的创建过程
成员变量的继承与隐藏
方法的继承与重写
【内容】
1.三角形、梯形和圆形的类封装
? 实验要求:
编写一个Java应用程序,该程序中有3个类:Trangle、Leder和Circle,分别用来刻画“三角形”、“梯形”和“圆形”。具体要求如下:
a) Trangle类具有类型为double的三个边,以及周长、面积属性,Trangle类具有返回周长、面积以及修改三个边的功能。另外,Trangle类还具有一个boolean型的属性,该属性用来判断三个属能否构成一个三角形。
b) Lader类具有类型double的上底、下底、高、面积属性,具有返回面积的功能。
c) Circle类具有类型为double的半径、周长和面积属性,具有返回周长、面积的功能。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
AreaAndLength.java
class Trangle
{
double sideA,sideB,sideC,area,length;
boolean boo;
public Trangle(double a,double b,double c)
{
【代码1】 //参数a,b,c分别赋值给sideA,sideB,sideC
if(【代码2】) //a,b,c构成三角形的条件表达式
{
【代码3】 //给boo赋值。
}
else
{
【代码4】 //给boo赋值。
}
10
}
double getLength()
{
【代码5】 //方法体,要求计算出length的值并返回
}
public double getArea()
{
if(boo)
{
double p=(sideA+sideB+sideC)/2.0;
area=Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC)) ;
return area;
}
else
{
System.out.println("不是一个三角形,不能计算面积"); return 0;
}
}
public void setABC(double a,double b,double c)
{
【代码6】 //参数a,b,c分别赋值给sideA,sideB,sideC
if(【代码7】) //a,b,c构成三角形的条件表达式
{
【代码8】 //给boo赋值。
}
else
{
【代码9】 //给boo赋值。
}
}
}
class Lader
{
double above,bottom,height,area;
Lader(double a,double b,double h)
{
【代码10】 //方法体,将参数a,b,c分别赋值给above,bottom,height }
double getArea()
{
【代码11】 //方法体,,要求计算出area返回
}
}
11
class Circle
{
double radius,area;
Circle(double r)
{
【代码12】 //方法体
}
double getArea()
{
【代码13】 //方法体,要求计算出area返回
}
double getLength()
{
【代码14】 //getArea方法体的代码,要求计算出length返回 }
void setRadius(double newRadius)
{
radius=newRadius;
}
double getRadius()
{
return radius;
}
}
public class AreaAndLength
{
public static void main(String args[])
{
double length,area;
Circle circle=null;
Trangle trangle;
Lader lader;
【代码15】 //创建对象circle
【代码16】 //创建对象trangle。
【代码17】 //创建对象lader
【代码18】 // circle调用方法返回周长并赋值给length System.out.println("圆的周长:"+length);
【代码19】 // circle调用方法返回面积并赋值给area System.out.println("圆的面积:"+area);
【代码20】 // trangle调用方法返回周长并赋值给length System.out.println("三角形的周长:"+length);
【代码21】 // trangle调用方法返回面积并赋值给area System.out.println("三角形的面积:"+area);
12
【代码22】 // lader调用方法返回面积并赋值给area
System.out.println("梯形的面积:"+area);
【代码23】 // trangle调用方法设置三个边,要求将三个边修改为12,34,1。
【代码24】 // trangle调用方法返回面积并赋值给area
System.out.println("三角形的面积:"+area);
【代码25】 // trangle调用方法返回周长并赋值给length
System.out.println("三角形的周长:"+length);
}
}
? 实验后的练习:
1. 程序中仅仅省略【代码15】,编译能通过吗?
2. 程序中仅仅省略【代码16】,编译能通过吗?
3. 程序中仅仅省略【代码15】,运行时出现怎样的异常提示?
4. 给Trangle类增加3个方法,分别用来返回3个边:sideA、sideB和sideC。
5. 让AreaAndLength类中的circle对象调用方法修改半径,然后输出修改后的
半径以及修改半径后的圆的面积和周长。
2.实例成员与类成员。
? 实验要求:
按程序模板的要求编写源文件,要特别注意程序的输出结果,并能正确解释输出的结果。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
Example.java
class A
{
【代码1】 //声明一个float型实例变量a
【代码2】 //声明一个float型类变量b,即static变量b
void setA(float a)
{
【代码3】 //将参数a的值赋值给成员变量a
}
void setB(float b)
{
【代码4】 //将参数b的值赋值给成员变量b
}
float getA()
{
return a;
}
float getB()
{
return b;
13
}
void inputA()
{
System.out.println(a);
}
static void inputB()
{
System.out.println(b);
}
}
public class Example
{
public static void main(String args[])
{
【代码5】 //通过类名操作类变量b,并赋值100
【代码6】 //通过类名调用方法inputB()
A cat=new A();
A dog=new A();
【代码7】 //cat象调用方法setA(int a)将cat的成员a的值设置为200
【代码8】 //cat调用方法setB(int b)将cat的成员b的值设置为400
【代码9】 //dog象调用方法setA(int a)将dog的成员a的值设置为150
【代码10】 //dog调用方法setB(int b)将dog的成员b的值设置为300
【代码11】 //cat调用inputA()。
【代码12】 //cat调用inputB()。
【代码13】 //dog调用inputA()。
【代码14】 //dog调用inputB()。
}
}
? 实验后的练习:
1. 将inputA()方法中的
System.out.println(a);
改写为
System.out.println(a+b);
编译是否出错?为什么?
2. 将inputB()方法中的
System.out.println(b);
改写为
System.out.println(a+b);
编译是否报错?为什么?
3.使用package语句与import语句。
? 实验要求:
按实验要求使用package语句,并用import语句使用Java平台提供的包中的类以及自定义包中的类。掌握一些重要的操作步骤。
? 程序运行效果示例:
14
程序运行效果如下图所示:
? 程序模板:
模板1:
将模板1给出的Java源文件命名为SquareEquation.java,将编译后得到的字节码文件复制到c:\1000\tom\jiafei目录中。
SquareEquation.java
package tom.jiafei;
public class SquareEquation
{
double a,b,c;
double root1,root2;
boolean boo;
public SquareEquation(double a,double b,double c)
{
this.a=a;
this.b=b;
this.c=c;
if(a!=0)
{
boo=true;
}
else
{
boo=false;
}
}
public void getRoots()
{
if(boo)
{
System.out.println("是一元2次方程");
double disk=b*b-4*a*c;
if(disk>=0)
{
root1=(-b+Math.sqrt(disk))/(2*a);
root2=(-b-Math.sqrt(disk))/(2*a);
System.out.printf("方程的根:%f,%f\n",root1,root2);
}
else
{
System.out.printf("方程没有实根\n");
}
15
}
else
{
System.out.println("不是一元2次方程");
}
}
public void setCoefficient(double a,double b,double c)
{
this.a=a;
this.b=b;
this.c=c;
if(a!=0)
{
boo=true;
}
else
{
boo=false;
}
}
}
模板2:
将模板2给出的Java源程序SunRise.java保存到d:\2000中。在编译模板2给出的Java源文件之前,要重新设置classpath。假设本地机SDK的安装目录是E:\jdk1.5。
在命令行执行如下命令: set classpath=e:\jdk1.5\jre\lib\rt.jar;.;c:\1000
然后编译模板2给出的Java源程序。或用鼠标右键点击“我的电脑”,弹出快捷菜单,然后选择“属性”命令,弹出“系统属性”对话框,再单击该对话框中的“高级”选项卡,然后单击“环境变量”按钮。将classpath的值修改为:
E:\jdk1.5\jre\lib\rt.jar;.;c:\1000 然后重新打开一个命令行窗口,编译模板2给出的Java源程序。 SunRise.java
import tom.jiafei.*;
class SunRise
{
public static void main(String args[ ])
{
SquareEquation equation=new SquareEquation(4,5,1);
equation.getRoots();
equation.setCoefficient(-3,4,5);
16
equation.getRoots();
}
}
假设SDK的安装目录是E:\jdk1.5,那么Java运行系统默认classpath的值? 实验后的练习:
是:E:\jdk1.5\jre\lib\rt.jar;.;
其中的“”表示应用程序可以使用当前目录中的无名包类以及当前目录下
的子目录中的类,子目录中的类必须有包名,而且包名要和子目录结构相对应。
因此,如果将模板2应用程序Sunrise.java的字节码文件存放到d:\5000
中,并将SquareEquation.java的字节码文件存放在D:\5000\tom\jiafei中,
那么就不需要修改classpath。要特别注意的是,因为SquareEquation.java
有包名,切不可将SquareEquation.java以及它的字节码文件存放在d:\5000
中,即不可以和Sunrise.java的字节码存放在一起,请进行如下的练习:
1. 将SquareEquation.java存放在D:\5000\tom\jiafei中,编译:
D:\5000\tom\jiafei\javac SquareEquation.java
2. 将Sunrise.java存放到D:\5000中,编译:
D:\5000\javac Sunrise.java
3. 运行:
java Sunrise
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
17
实验四 字符串、时间与数字类
【目的】
①掌握String类的常用方法
②掌握Date类以及Calendar类的常用方法;
③掌握BigInteger类的常用方法。
【内容】
1.String类的常用方法。
? 实验要求:
编写一个Java应用程序,判断两个字符串是否相同,判断字符串的前缀、后缀是否和某个字符串相同,按字典顺序比较两个字符串的大小关系,检索字符串,创建字符串,将数字型字符串转换为数字,将字符串存放到数组中,用字符数组创建字符串。。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
StringExample.java
class StringExample
{ public static void main(String args[])
{ String s1=new String("you are a student"),
s2=new String("how are you");
if(【代码1】) // 使用equals方法判断s1与s2是否相同
{
System.out.println("s1与s2相同");
}
else
{
System.out.println("s1与s2不相同");
}
String s3=new String("22030219851022024");
if(【代码2】) //判断s3的前缀是否是“220302”。
{
System.out.println("吉林省的身份证");
}
String s4=new String("你"),
s5=new String("我");
if(【代码3】)//按着字典序s4大于s5的表达式。
{
System.out.println("按字典序s4大于s5");
}
else
{
18
System.out.println("按字典序s4小于s5");
}
int position=0;
String path="c:\\java\\jsp\\A.java";
position=【代码5】 //获取path中最后出现目录分隔符号的位置
System.out.println("c:\\java\\jsp\\A.java中最后出现\\的位置:"+position); String fileName=【代码6】//获取path中“A.java”子字符串。
System.out.println("c:\\java\\jsp\\A.java中含有的文件名:"+fileName); String s6=new String("100"),
s7=new String("123.678");
int n1=【代码7】 //将s6转化成int型数据。
double n2=【代码8】 //将s7转化成double型数据。
double m=n1+n2;
System.out.println(m);
String s8=【代码9】 //String调用valuOf(int n)方法将m转化为字符串对象 position=s8.indexOf(".");
String temp=s8.substring(position+1);
System.out.println("数字"+m+"有"+temp.length()+"位小数") ;
String s9=new String("ABCDEF");
char a[]=【代码10】 //将s8存放到数组a中。
for(int i=a.length-1;i>=0;i--)
{
System.out.print(" "+a[i]);
}
}
}
? 实验后的练习:
1. 程序中的s6改写成
String s6=new String(“1a12b”);
运行时提示怎样的错误?
2. 请用数组a的前3个单元创建一个字符串并输出该串。
3. 请给出获取path中“jsp”子字符串的代码。
4. 在程序的适当位置增加如下代码,注意输出的结果。
String str1=new String(“ABCABC”),
str2=null, str3=null, str4=null;
str2=str1.replaceAll(“A”,”First”);
str3=str2.replaceAll(“B”,”Second”);
str4=str3.replaceAll(“C”,”Third”);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println(str4);
19
5. 可以使用Long类中的下列static方法得到整数各种进制的字符串表示: Public static String toBinaryString(long i)
Public static String toOctalString(long i)
Public static String toHexString(long i)
Public static String toString(long i,int p)
其中的toString(long i, int p)返回整数i的p进制表示。请在适当位置添加代码输出12345的二进制、八进制和十六进制表示。
6. 在适当位置添加代码,分别输出数字m的整数部分和小数部分。
2.比较日期的大小。
? 实验要求:
编写一个Java应用程序,用户从输入对话框输入了两个日期,程序将判断两个日期的大小关系,以及两个日期之间的间隔天数。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
DateExample
import java.util.*;
import javax.swing.JOptionPane;
public class DateExample
{
public static void main(String args[ ])
{
String str=JOptionPane.showInputDialog("输入第一个日期的年份:");
int yearOne=Integer.parseInt(str);
str=JOptionPane.showInputDialog("输入该年的月份:");
int monthOne=Integer.parseInt(str);
str=JOptionPane.showInputDialog("输入该月份的日期:");
int dayOne=Integer.parseInt(str);
str=JOptionPane.showInputDialog("输入第二个日期的年份:");
int yearTwo=Integer.parseInt(str);
str=JOptionPane.showInputDialog("输入该年的月份:");
int monthTwo=Integer.parseInt(str);
str=JOptionPane.showInputDialog("输入该月份的日期:");
int dayTwo=Integer.parseInt(str);
Calendar calendar=【代码1】 //初始化日历对象
【代码2】 //将calendar的时间设置为yearOne年monthOne月dayOne日
long timeOne=【代码3】 //calendar表示的时间转换成毫秒
【代码4】 //将calendar的时间设置为yearTwo年monthTwo月dayTwo日
long timeTwo=【代码5】 //calendar表示的时间转换成毫秒。
20
Date date1=【代码6】 // 用timeOne做参数构造date1
Date date2=【代码7】 // 用timeTwo做参数构造date2
if(date2.equals(date1))
{
System.out.println("两个日期的年、月、日完全相同");
}
else if(date2.after(date1))
{
System.out.println("您输入的第二个日期大于第一个日期");
}
else if(date2.before(date1))
{
System.out.println("您输入的第二个日期小于第一个日期");
}
long days=【代码8】//计算两个日期相隔天数
System.out.println(yearOne+"年"+monthOne+"月"+dayOne+"日和"
+yearTwo+"年"+monthTwo+"月"+dayTwo+"相隔"+days+"天");
}
}
? 实验后的练习:
1. Calendar对象可以将时间设置到年、月、日、时、分、秒。请改进上面的程序,使用户输入的两个日期包括时、分、秒。
2. 根据本程序中的一些知识,编写一个计算利息(按天计算)的程序。从输入对话框输入存款的数目和起止时间。
3.处理大整数。
? 实验要求:
编写一个Java应用程序,计算两个大整数的和、差、积和商,并计算一个大整数的因子个数(因子中不包括1和大整数本身)。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
BigintegerExample
import java.math.*;
class BigIntegerExample
{
public static void main(String args[])
{ BigInteger n1=new BigInteger("987654321987654321987654321"),
n2=new BigInteger("123456789123456789123456789"),
result=null;
21
result=【代码1】//n1和n2做加法运算
System.out.println("和:"+result.toString());
result=【代码2】//n1和n2做减法运算
System.out.println("差:"+result.toString());
result=【代码3】//n1和n2做乘法运算
System.out.println("积:"+result.toString());
result=【代码4】//n1和n2做除法运算
System.out.println("商:"+result.toString());
BigInteger m=new BigInteger("1968957"),
COUNT=new BigInteger("0"),
ONE=new BigInteger("1"),
TWO=new BigInteger("2");
System.out.println(m.toString()+"的因子有:");
for(BigInteger i=TWO;i.compareTo(m)<0;i=i.add(ONE))
{ if((n1.remainder(i).compareTo(BigInteger.ZERO))==0)
{ COUNT=COUNT.add(ONE);
System.out.print(" "+i.toString());
}
}
System.out.println("");
System.out.println(m.toString()+"一共有"+COUNT.toString()+"个因子"); }
}
? 实验后的练习:
1. 编写程序,计算大整数的阶乘。
2. 编写程序,计算1+2+3…的前999999999项的和。
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
22
实验五 组件与事件处理
【目的】
①学习处理ActionEvent事件;
②学习处理ItemEvent事件和paint方法;
③学习使用布局类。
【内容】
1.算术测试。
? 实验要求:
编写一个算书测试小软件,用来训练小学生的算术能力。程序由3个类组成,其中Teacher类对象负责给出算术题目,并判断回答者的答案是否正确;ComputerFrame类对象负责为算术题目提供视图,比如用户可以通过ComputerFrame类对象提供的GUI界面看到题目,并通过该GUI界面给出题目的答案;MainClass是软件的主类。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
Teacher.java
public class Teacher
{ int numberOne,numberTwo;
String operator="";
boolean right;
public int giveNumberOne(int n)
{ numberOne=(int)(Math.random()*n)+1;
return numberOne;
}
public int giveNumberTwo(int n)
{ numberTwo=(int)(Math.random()*n)+1;
return numberTwo;
}
public String giveOperator()
{ double d=Math.random();
if(d>=0.5)
operator="+";
else
operator="-";
return operator;
}
public boolean getRight(int answer)
{ if(operator.equals("+"))
{ if(answer==numberOne+numberTwo)
23
right=true;
else
right=false;
}
else if(operator.equals("-"))
{ if(answer==numberOne-numberTwo)
right=true;
else
right=false;
}
return right;
}
}
ComputerFrame.java
import java.awt.*;
import java.awt.event.*;
public class ComputerFrame extends Frame implements ActionListener { TextField textOne,textTwo,textResult;
Button getProblem,giveAnwser;
Label operatorLabel,message;
Teacher teacher;
ComputerFrame(String s)
{ super(s);
teacher=new Teacher();
setLayout(new FlowLayout());
textOne=【代码1】 //创建textOne,其可见字符长是10 textTwo=【代码2】 //创建textTwo,其可见字符长是10 textResult=【代码3】 //创建textResult,其可见字符长是10 operatorLabel=new Label("+");
message=new Label("你还没有回答呢");
getProblem=new Button("获取题目");
giveAnwser=new Button("确认答案");
add(getProblem);
add(textOne);
add(operatorLabel);
add(textTwo);
add(new Label("="));
add(textResult);
add(giveAnwser);
add(message);
textResult.requestFocus();
textOne.setEditable(false);
textTwo.setEditable(false);
【代码4】//将当前窗口注册为getProblem的ActionEvent事件监视器
24
【代码5】//将当前窗口注册为giveAnwser的ActionEvent事件监视器
【代码6】//将当前窗口注册为textResult的ActionEvent事件监视器 setBounds(100,100,450,100);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
}
public void actionPerformed(ActionEvent e)
{ if(【代码7】) //判断事件源是否是getProblem
{ int number1=teacher.giveNumberOne(100);
int number2=teacher.giveNumberTwo(100);
String operator=teacher.givetOperator();
textOne.setText(""+number1);
textTwo.setText(""+number2);
operatorLabel.setText(operator);
message.setText("请回答");
textResult.setText(null);
}
if(【代码8】) //判断事件源是否是giveAnwser
{ String answer=textResult.getText();
try{
int result=Integer.parseInt(answer);
if(teacher.getRight(result)==true)
{ message.setText("你回答正确");
}
else
{ message.setText("你回答错误");
}
}
catch(NumberFormatException ex)
{ message.setText("请输入数字字符");
}
}
textResult.requestFocus();
validate();
}
}
MainClass.java
public class MainClass
25
{ public static void main(String args[])
{ ComputerFrame frame;
frame=【代码9】//创建窗口,其标题为:算术测试
}
}
? 实验后的练习:
1. 给上述程序增加测试乘、除的功能。
2.信号灯。
? 实验要求:
编写一个带有窗口的应用程序。在窗口的北面添加一个下拉列表,该下拉列表有“”、“”和“”三个选项。在窗口的中心添加一个画布,当用户在下拉列表选择某项后,画布上绘制相应的信号灯。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
SignalCanvas.java
import java.awt.*;
public class SignalCanvas extends Canvas
{ int red,green,yellow,x,y,r;
SignalCanvas()
{ setBackground(Color.white);
}
public void setRed(int r)
{ red=r;
}
public void setGreen(int g)
{ green=g;
}
public void setYellow(int y)
{ yellow=y;
}
public void setPosition(int x,int y)
{ this.x=x;
this.y=y;
}
public void setRadius(int r)
{ this.r=r;
}
public void paint(Graphics g)
{ if(red==1)
{ g.setColor(Color.red);
}
26
else if(green==1)
{ g.setColor(Color.green);
}
else if(yellow==1)
{ g.setColor(Color.yellow);
}
g.fillOval(x,y,2*r,2*r);
}
}
SignalFrame.java
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class SignalFrame extends Frame implements ItemListener { Choice choice;
SignalCanvas signal=null;
String itemRed="红灯",itemYellow="黄灯",itemGreen="绿灯"; public SignalFrame()
{ choice=【代码1】 //创建choice
【代码2】 //创建choice添加itemRed
【代码3】 //创建choice添加itemYellow
【代码4】 //创建choice添加itemGreen
【代码5】 //将当前窗口注册为choice的ItemEvent事件监视器 add(choice,BorderLayout.NORTH);
try{ Class cs=Class.forName("SignalCanvas");
signal=(SignalCanvas)cs.newInstance();
add(signal,BorderLayout.CENTER);
}
catch(Exception e)
{ add(new Label("您还没有编写SignalCanvas"),BorderLayout.CENTER);
}
setBounds(100,100,360,300);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
}
public void itemStateChanged(ItemEvent e)
{ String item= 【代码6】 // choice返回被选中的条目
27 类
int w=signal.getBounds().width;
int h=signal.getBounds().height;
int m=Math.min(w,h);
signal.setRadius(m/6);
if(item.equals(itemRed))
{ if(signal!=null)
{ signal.setRed(1);
signal.setYellow(0);
signal.setGreen(0);
signal.setPosition(w/3,0);
signal.repaint();
}
}
else if(item.equals(itemYellow))
{ if(signal!=null)
{ signal.setRed(0);
signal.setYellow(1);
signal.setGreen(0);
signal.setPosition(w/3,h/3);
signal.repaint();
}
}
else if(item.equals(itemGreen))
{ if(signal!=null)
{ signal.setRed(0);
signal.setYellow(0);
signal.setGreen(1);
signal.setPosition(w/3,2*h/3);
signal.repaint();
}
}
}
}
SignalMainClass.java
public class SignalMainClass
{ public static void main(String args[])
{ SignalFrame frame;
frame=new SignalFrame() ;
frame.setTitle("信号灯");
}
}
? 实验后的练习:
1. 改进上述程序,在下拉列表中增加“熄灭所有灯”选项,当选中该项时,画布上绘制一个半径为0,位置是(0,0)的圆。
28
3.布局与日历。
? 实验要求:
编写一个应用程序,有一个窗口,该窗口为BorderLayout布局。窗口的中心添加一个Panel容器:pCenter,pCenter的布局是7行7列的GriderLayout布局,pCenter中放置49个标签,用来显示日历。窗口的北面添加一个Panel容器pNorth,其布局是FlowLayout布局,pNorth放置两个按钮:nextMonth和previousMonth,单击nextMonth按钮,可以显示当前月的下一月的日历;单击previousMonth按钮,可以显示当前月的上一月的日历。窗口的南面添加一个Panel容器pSouth,其布局是FlowLayout布局,pSouth中放置一个标签用来显示一些信息。
? 程序运行效果示例:
程序运行效果如下图所示:
CalendarBean.java
import java.util.Calendar;
public class CalendarBean
{
String day[];
int year=2005,month=0;
public void setYear(int year)
{ this.year=year;
}
public int getYear()
{ return year;
}
public void setMonth(int month)
{ this.month=month;
}
public int getMonth()
{ return month;
}
public String[] getCalendar()
{ String a[]=new String[42];
Calendar 日历=Calendar.getInstance();
日历.set(year,month-1,1);
int 星期几=日历.get(Calendar.DAY_OF_WEEK)-1;
int day=0;
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) { day=31;
}
if(month==4||month==6||month==9||month==11)
{ day=30;
} ? 程序模板:
29
if(month==2)
{ if(((year%4==0)&&(year%100!=0))||(year%400==0))
{ day=29;
}
else
{ day=28;
}
}
for(int i=星期几,n=1;i<星期几+day;i++)
{
a[i]=String.valueOf(n) ;
n++;
}
return a;
}
}
CalendarFrame.java
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class CalendarFrame extends Frame implements ActionListener
{ Label labelDay[]=new Label[42];
Button titleName[]=new Button[7];
String name[]={"日","一","二","三", "四","五","六"};
Button nextMonth,previousMonth;
int year=2006,month=10;
CalendarBean calendar;
Label showMessage=new Label("",Label.CENTER);
public CalendarFrame()
{ Panel pCenter=new Panel();
【代码1】 //将pCenter的布局设置为7行7列的GridLayout 布局。 for(int i=0;i<7;i++)
{ titleName[i]=new Button(name[i]);
【代码2】//pCenter添加组件titleName[i]。
}
for(int i=0;i<42;i++)
{
labelDay[i]=new Label("",Label.CENTER);
【代码3】//pCenter添加组件labelDay[i]。
}
calendar=new CalendarBean();
calendar.setYear(year);
calendar.setMonth(month);
30
String day[]=calendar.getCalendar();
for(int i=0;i<42;i++)
{ labelDay[i].setText(day[i]);
}
nextMonth=new Button("下月");
previousMonth=new Button("上月");
nextMonth.addActionListener(this);
previousMonth.addActionListener(this);
Panel pNorth=new Panel(),
pSouth=new Panel();
pNorth.add(previousMonth);
pNorth.add(nextMonth);
pSouth.add(showMessage);
showMessage.setText("日历:"+calendar.getYear()+"年"+ calendar.getMonth()+"月" );
ScrollPane scrollPane=new ScrollPane();
scrollPane.add(pCenter);
【代码4】// 窗口添加scrollPane在中心区域
【代码5】// 窗口添加pNorth 在北面区域
【代码6】// 窗口添加pSouth 在南区域。
}
public void actionPerformed(ActionEvent e)
{ if(e.getSource()==nextMonth)
{ month=month+1;
if(month>12)
month=1;
calendar.setMonth(month);
String day[]=calendar.getCalendar();
for(int i=0;i<42;i++)
{ labelDay[i].setText(day[i]);
}
}
else if(e.getSource()==previousMonth)
{ month=month-1;
if(month<1)
month=12;
calendar.setMonth(month);
String day[]=calendar.getCalendar();
for(int i=0;i<42;i++)
{ labelDay[i].setText(day[i]);
}
}
showMessage.setText("日历:"+calendar.getYear()+"年"+calendar.getMonth()+"月" );
31
}
}
CalendarMainClass.java
public class CalendarMainClass
{ public static void main(String args[])
{ CalendarFrame frame=new CalendarFrame();
frame.setBounds(100,100,360,300);
frame.setVisible(true);
frame.validate();
frame.addWindowListener(new java.awt.event.WindowAdapter()
{
windowClosing(java.awt.event.WindowEvent e)
{ System.exit(0);
}
}
);
}
} public void
? 实验后的练习:
1. 请在CalendarFrame类中增加一个TextField文本框,用户可以通过在文本框中输入年份来修改calendar对象的int成员year。
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
32
实验六 多线程
【目的】
①掌握使用Thread的子类创建线程;
②学习使用Thread类创建线程;
③学习处理线程同步问题。
【内容】
1.汉字打字练习。
? 实验要求:
编写一个Java应用程序,在主线程中再创建一个Frame类型的窗口,在该窗口中再创建1个线程giveWord。线程giveWord每隔2秒钟给出一个汉字,用户使用一种汉字输入法将该汉字输入到文本框中。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
WordThread.java
import java.awt.*;
public class WordThread extends Thread
{ char word;
int k=19968;
Label com;
WordThread(Label com)
{ this.com=com;
}
public void run()
{ k=19968;
while(true)
{
word=(char)k;
com.setText(""+word);
try{ 【代码1】//调用sleep方法使得线程中断6000豪秒
}
catch(InterruptedException e){}
k++;
if(k>=29968) k=19968;
}
}
}
ThreadFrame.java
import java.awt.*;
import java.awt.event.*;
public class ThreadFrame extends Frame implements ActionListener
33
{
Label wordLabel;
Button button;
TextField inputText,scoreText;
【代码2】//用WordThread声明一个giveWord对象
int score=0;
ThreadFrame()
{ wordLabel=new Label(" ",Label.CENTER);
wordLabel.setFont(new Font("",Font.BOLD,72));
button=new Button("开始");
inputText=new TextField(3);
scoreText=new TextField(5);
scoreText.setEditable(false);
【代码3】//创建giveWord,将wordLabel传递给WordThread构造方法的参数 button.addActionListener(this);
inputText.addActionListener(this);
add(button,BorderLayout.NORTH);
add(wordLabel,BorderLayout.CENTER);
Panel southP=new Panel();
southP.add(new Label("输入标签所显示的汉字后回车:"));
southP.add(inputText);
southP.add(scoreText);
add(southP,BorderLayout.SOUTH);
setBounds(100,100,350,180);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==button)
{ if(!(【代码4】)) //giveWord调用方法isAlive()
{ giveWord=new WordThread(wordLabel);
}
try
{ 【代码5】//giveWord调用方法start()
}
catch(Exception exe){}
}
34
else if(e.getSource()==inputText)
{ if(inputText.getText().equals(wordLabel.getText()))
{ score++;
}
scoreText.setText("得分:"+score);
inputText.setText(null);
}
}
}
WordThread.java
public class ThreadWordMainClass
{ public static void main(String args[])
{ new ThreadFrame();
}
? 实验后的练习:
1. 在WordThread类中增加int型的成员time,其初值为6000,将其中的【代码1】更改为线程中断time毫秒。在WordThread类增加public void setTime(int n)方法,使得WordThread线程对象可以调用该方法修改time的值。
2.旋转的行星。
? 实验要求:
编写一个应用程序,模拟月亮围绕地球旋转、地球围绕太阳旋转。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
Mycanvas.java
import java.awt.*;
public class Mycanvas extends Canvas
{ int r;
Color c;
public void setColor(Color c)
{ this.c=c;
}
public void setR(int r)
{ this.r=r;
}
public void paint(Graphics g)
{ g.setColor(c);
g.fillOval(0,0,2*r,2*r);
}
public int getR()
{ return r;
35
}
}
Planet.java
import java.awt.*;
public class Planet extends Panel implements Runnable
{ 【代码1】 //用Thread类声明一个moon对象
Mycanvas yellowBall;
double pointX[]=new double[360],
pointY[]=new double[360]; //用来表示画布左上角端点坐标的数组 int w=100,h=100;
int radius=30;
Planet()
{ setSize(w,h);
setLayout(null);
yellowBall=new Mycanvas();
yellowBall.setColor(Color.yellow);
add(yellowBall);
yellowBall.setSize(12,12);
yellowBall.setR(12/2);
pointX[0]=0;
pointY[0]=-radius;
double angle=1*Math.PI/180; //刻度为1度
for(int i=0;i<359;i++) //计算出数组中各个元素的值
{ pointX[i+1]=pointX[i]*Math.cos(angle)-Math.sin(angle)*pointY[i]; pointY[i+1]=pointY[i]*Math.cos(angle)+pointX[i]*Math.sin(angle); }
for(int i=0;i<360;i++)
{ pointX[i]=pointX[i]+w/2; //坐标平移
pointY[i]=pointY[i]+h/2;
}
yellowBall.setLocation((int)pointX[0]-yellowBall.getR(),
(int)pointY[0]-yellowBall.getR());
【代码2】 //创建 moon线程,当前面板做为该线程的目标对象
}
public void start()
{ try{ moon .start();
}
catch(Exception exe){}
}
public void paint(Graphics g)
{ g.setColor(Color.blue);
g.fillOval(w/2-9,h/2-9,18,18);
}
public void run()
36
{ int i=0;
while(true)
{ i=(i+1)%360;
yellowBall.setLocation((int)pointX[i]-yellowBall.getR(),
(int)pointY[i]-yellowBall.getR());
try{ 【代码3】 // Thread类调用类方法sleep使得线程中断10豪秒 }
catch(InterruptedException e){}
}
}
}
HaveThreadFrame.java
import java.awt.*;
import java.awt.event.*;
public class HaveThreadFrame extends Frame implements Runnable
{ 【代码4】 //用Thread类声明一个rotate对象
Planet earth;
double pointX[]=new double[360],
pointY[]=new double[360];
int width,height;
int radius=120;
HaveThreadFrame()
{ rotate=new Thread(this);
earth=new Planet();
setBounds(0,0,360,400);
width=getBounds().width;
height=getBounds().height;
pointX[0]=0;
pointY[0]=-radius;
double angle=1*Math.PI/180;
for(int i=0;i<359;i++)
{ pointX[i+1]=pointX[i]*Math.cos(angle)-Math.sin(angle)*pointY[i]; pointY[i+1]=pointY[i]*Math.cos(angle)+pointX[i]*Math.sin(angle); }
for(int i=0;i<360;i++)
{ pointX[i]=pointX[i]+width/2;
pointY[i]=pointY[i]+height/2;
}
setLayout(null);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
37
}
}
);
add(earth);
earth.setLocation((int)pointX[0]-earth.getSize().width/2,
(int)pointY[0]-earth.getSize().height/2);
earth.start();
【代码5】 //用rotate调用start方法
}
public void run()
{ int i=0;
while(true)
{ i=(i+1)%360;
earth.setLocation((int)pointX[i]-earth.getSize().width/2,
(int)pointY[i]-earth.getSize().height/2); try{ Thread.sleep(100);
}
catch(InterruptedException e){}
}
}
public void paint(Graphics g)
{ g.setColor(Color.red);
g.fillOval(width/2-15,height/2-15,30,30);
}
}
HaveThreadFrame.java
public class ThreadRotateMainClass
{ public static void main(String args[])
{ new HaveThreadFrame();
}
}
? 实验后的练习:
1. 在Planet类中再增加一个Mycanvas对象greenBall和一个Thread对象
Satellite,线程Satellite占有CPU资源期间可以让greenBall画布旋转。
3.双线程接力。
? 实验要求:
编写一个应用程序,除了主线程外,还有两个线程:first和second。first负责模拟一个红色的按钮从坐标(10,60)运动到(100,60);second负责模拟一个绿色的按钮从坐标(100,60)运动到(200,60)。
? 程序运行效果示例:
程序运行效果如下图所示:
38
? 程序模板:
MoveButton.java
import java.awt.*;
import java.awt.event.*;
public class MoveButton extends Frame implements Runnable,ActionListener { 【代码1】//用Thread类声明first,second两个线程对象
Button redButton,greenButton,startButton;
int distance=10;
MoveButton()
{ 【代码2】 //创建first线程,当前窗口做为该线程的目标对象
【代码3】 //创建first线程,当前窗口做为该线程的目标对象 redButton=new Button();
greenButton=new Button();
redButton.setBackground(Color.red);
greenButton.setBackground(Color.green);
startButton=new Button("start");
startButton.addActionListener(this);
setLayout(null);
add(redButton);
redButton.setBounds(10,60,15,15);
add(greenButton);
greenButton.setBounds(100,60,15,15);
add(startButton);
startButton.setBounds(10,100,30,30);
setBounds(0,0,300,200);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
}
public void actionPerformed(ActionEvent e)
{ try{ first.start();
second.start();
}
catch(Exception exp){}
}
public void run()
{ while(true)
{ if(【代码4】) //判断当前占有CPU资源的线程是否是first { moveComponent(redButton);
39
try{ Thread.sleep(20);
}
catch(Exception exp){}
}
if(【代码5】) //判断当前占有CPU资源的线程是否是second { moveComponent(greenButton);
try{ Thread.sleep(10);
}
catch(Exception exp){}
}
}
}
public synchronized void moveComponent(Component b)
{
if(Thread.currentThread()==first)
{ while(distance>100&&distance<=200)
try{ wait();
}
catch(Exception exp){}
distance=distance+1;
b.setLocation(distance,60);
if(distance>=100)
{ b.setLocation(10,60);
notifyAll();
}
}
if(Thread.currentThread()==second)
{ while(distance>=10&&distance<100)
try{ wait();
}
catch(Exception exp){}
distance=distance+1;
b.setLocation(distance,60);
if(distance>200)
{ distance=10;
b.setLocation(100,60);
notifyAll();
}
}
}
}
MoveButtonMainClass.java
public class MoveButtonMainClass
{ public static void main(String args[])
40
{ new MoveButton();
}
? 实验后的练习:
1. 在MoveButton类中再增加一个蓝色的按钮和一个third线程,third线程负责将这个蓝色的按钮从(200,60)运动到(300,60)。
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
41
实验七 输入输出流
【目的】
①掌握字符输入、输出流的用法;
②掌握RandomAccessFil类的使用;
③掌握ZipInputStream流的使用。
【内容】
1.学读汉字。
? 实验要求:
编写一个Java应用程序,要求如下:
(1)可以将一个由汉字字符组成的文本文件读入到程序中;
(2)单击名为“下一个汉字”的按钮,可以在一个标签中显示程序读入的一个汉字;
(3)单击名为“发音”的按钮,可以听到标签上显示的汉字的读音。
(4)用户可以使用文本编辑器编辑程序中用到的3个由汉字字符组成的文本文件:training1.txt、training2.txt和training.txt,这些文本文件中的汉字需要用空格、逗号或回车分隔。
()需要自己制作相应的声音文件,比如:training1.txt文件包含汉字“你”,那么在当前应用程序的运行目录中需要有“你.wav”格式的声音文件。
()用户选择“帮助”菜单,可以查看软件的帮助信息。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
ChineseCharacters.java
import java.io.*;
import java.util.StringTokenizer;
public class ChineseCharacters
{ public StringBuffer getChinesecharacters(File file)
{ StringBuffer hanzi=new StringBuffer();
try{ FileReader inOne=【代码1】 //创建指向文件f的inOne 的对象
BufferedReader inTwo=【代码2】//创建指向文件inOne的inTwo的对象 String s=null;
int i=0;
while((s=【代码3】)!=null) //inTwo读取一行
{ StringTokenizer tokenizer=new StringTokenizer(s," ,'\n' "); while(tokenizer.hasMoreTokens())
{ hanzi.append(tokenizer.nextToken());
}
}
}
catch(Exception e) {}
42
return hanzi;
}
}
StudyFrame.java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class StudyFrame extends Frame ItemListener,ActionListener,Runnable
{ ChineseCharacters chinese;
Choice choice;
Button getCharacters,voiceCharacters;
Label showCharacters;
StringBuffer trainedChinese=null;
Clip clip=null;
Thread voiceThread;
int k=0;
Panel pCenter;
CardLayout mycard;
TextArea textHelp;
MenuBar menubar;
Menu menu;
MenuItem help;
public StudyFrame()
{ chinese=new ChineseCharacters();
choice=new Choice();
choice.add("training1.txt");
choice.add("training2.txt");
choice.add("training3.txt");
showCharacters=new Label("",Label.CENTER);
showCharacters.setFont(new Font("宋体",Font.BOLD,72)); showCharacters.setBackground(Color.green);
getCharacters=new Button("下一个汉字");
voiceCharacters=new Button("发音");
voiceThread=new Thread(this);
choice.addItemListener(this);
voiceCharacters.addActionListener(this);
getCharacters.addActionListener(this);
Panel pNorth=new Panel();
pNorth.add(new Label("选择一个汉字字符组成的文件")); pNorth.add(choice);
add(pNorth,BorderLayout.NORTH);
Panel pSouth=new Panel();
43 implements
pSouth.add(getCharacters);
pSouth.add(voiceCharacters);
add(pSouth,BorderLayout.SOUTH);
pCenter=new Panel();
mycard=new CardLayout();
pCenter.setLayout(mycard);
textHelp=new TextArea();
pCenter.add("hanzi",showCharacters);
pCenter.add("help",textHelp);
add(pCenter,BorderLayout.CENTER);
menubar=new MenuBar();
menu=new Menu("帮助");
help=new MenuItem("关于学汉字");
help.addActionListener(this);
menu.add(help);
menubar.add(menu);
setMenuBar(menubar);
setSize(350,220);
setVisible(true);
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
});
validate();
}
public void itemStateChanged(ItemEvent e)
{ String fileName=choice.getSelectedItem();
File file=new File(fileName);
trainedChinese=chinese.getChinesecharacters(file); k=0;
mycard.show(pCenter,"hanzi") ;
}
public void actionPerformed(ActionEvent e)
{ if(e.getSource()==getCharacters)
{ if(trainedChinese!=null)
{ char c=trainedChinese.charAt(k);
k++;
if(k>=trainedChinese.length())
k=0;
showCharacters.setText(""+c);
}
else
{ showCharacters.setText("请选择一个汉字字符文件");
44
}
}
if(e.getSource()==voiceCharacters)
{ if(!(voiceThread.isAlive()))
{ voiceThread=new Thread(this);
}
try{ voiceThread.start();
}
catch(Exception exp){}
}
if(e.getSource()==help)
{ mycard.show(pCenter,"help") ;
try{ File helpFile=new File("help.txt");
FileReader inOne=【代码4】 //创建指向文件helpFile的inOne 的对象
BufferedReader inTwo=【代码5】 //创建指向文件inOne的inTwo 的对象
String s=null;
while((s=inTwo.readLine())!=null)
{ textHelp.append(s+"\n");
}
inOne.close();
inTwo.close();
}
catch(IOException exp){}
}
}
public void run()
{ voiceCharacters.setEnabled(false);
try{ if(clip!=null)
{ clip.close()
}
clip=AudioSystem.getClip();
File
File(showCharacters.getText().trim()+".wav");
clip.open(AudioSystem.getAudioInputStream(voiceFile)); }
catch(Exception exp){}
clip.start();
voiceCharacters.setEnabled(true);
}
} voiceFile=new
StudyMainClass.java
public class StudyMainClass
45
{ public static void main(String args[])
{ new StudyFrame();
}
}
? 实验后的练习:
1. 在StudyFrame类中增加一个按钮previousButton,单击该按钮可以读取前一个汉字。
2.统计英文单词。
? 实验要求:
使用RandomAccessFile流统计一篇英文中的单词,要求如下:
(1)一共出现了多少个单词;
(2)有多少个互不相同的单词;
(3)给出每个单词出现的频率,并将这些单词按频率大小顺序显示在一个TextArea中。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
WordStatistic.java
import java.io.*;
import java.util.Vector;
public class WordStatistic
{ Vector allWorsd,noSameWord;
WordStatistic()
{ allWorsd=new Vector();
noSameWord=new Vector();
}
public void wordStatistic(File file)
{ try{ RandomAccessFile inOne=【代码1】 //创建指向文件file的inOne 的对象
RandomAccessFile inTwo=【代码2】 //创建指向文件file的inTwo 的对象
long wordStarPostion=0,wordEndPostion=0;
long length=inOne.length();
int flag=1;
int c=-1;
for(int k=0;k<=length;k++)
{ c=【代码3】 // inOne调用read()方法
boolean boo=(c<='Z'&&c>='A')||(c<='z'&&c>='a');
if(boo)
{ if(flag==1)
{ wordStarPostion=inOne.getFilePointer()-1;
46
flag=0;
}
}
else
{ if(flag==0)
{
if(c==-1)
wordEndPostion=inOne.getFilePointer(); else
wordEndPostion=inOne.getFilePointer()-1;
【代码4】// inTwo调用seek方法将读写位置移动到wordStarPostion
byte
byte[(int)wordEndPostion-(int)wordStarPostion];
【代码5】// inTwo调用readFully(byte a)方法,向a传递cc
String word=new String(cc);
allWorsd.add(word);
if(!(noSameWord.contains(word)))
noSameWord.add(word);
}
flag=1;
}
}
inOne.close();
inTwo.close();
}
catch(Exception e){}
}
public Vector getAllWorsd()
{ return allWorsd;
}
public Vector getNoSameWord()
{ return noSameWord;
}
} cc[]=new
RandomExample.java
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.io.File;
public class StatisticFrame extends Frame implements ActionListener { WordStatistic statistic;
47
TextArea showMessage;
Button openFile;
FileDialog openFileDialog;
Vector allWord,noSameWord;
public StatisticFrame()
{ statistic=new WordStatistic();
showMessage=new TextArea();
openFile=new Button("Open File");
openFile.addActionListener(this);
add(openFile,BorderLayout.NORTH);
add(showMessage,BorderLayout.CENTER);
openFileDialog=new FileDialog(this,"打开文件话框",FileDialog.LOAD); allWord=new Vector();
noSameWord=new Vector();
setSize(350,300);
setVisible(true);
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e)
{ System.exit(0);
}
});
validate();
}
public void actionPerformed(ActionEvent e)
{ noSameWord.clear();
allWord.clear();
showMessage.setText(null);
openFileDialog.setVisible(true);
String fileName=openFileDialog.getFile();
if(fileName!=null)
{ statistic.wordStatistic(new File(fileName));
allWord=statistic.getAllWorsd();
noSameWord=statistic.getNoSameWord();
showMessage.append("\n"+fileName+"中有"+allWord.size()+"个英文单词");
showMessage.append("\n其中有"+noSameWord.size()+"个互不相同英文单词");
showMessage.append("\n按使用频率排列:\n");
int count[]=new int[noSameWord.size()];
for(int i=0;i<noSameWord.size();i++)
{ String s1=(String)noSameWord.elementAt(i);
for(int j=0;j<allWord.size();j++)
{ String s2=(String)allWord.elementAt(j);
if(s1.equals(s2))
48
count[i]++;
}
}
for(int m=0;m<noSameWord.size();m++)
{ for(int n=m+1;n<noSameWord.size();n++)
{ if(count[n]>count[m])
{ String temp=(String)noSameWord.elementAt(m);
noSameWord.setElementAt((String)noSameWord.elementAt(n),m);
noSameWord.setElementAt(temp,n);
int t=count[m];
count[m]=count[n];
count[n]=t;
}
}
}
for(int m=0;m<noSameWord.size();m++)
{ showMessage.append("\n"+(String)noSameWord.elementAt(m)+ ":"+count[m]+"/"+allWord.size()+
"="+(1.0*count[m])/allWord.size()); }
}
}
}
RandomExample.java
public class StatisticMainClass
{ public static void main(String args[])
{ new StatisticFrame();
}
}
? 实验后的练习:
1. 在StatisticFrame的showMessage中增加单词按字典序排序输出的信息。
3.读取Zip文件。
? 实验要求:
读取book.zip,并将book.zip中含有的文件重新存放到当前目录中的book文件夹中,即将book.zip的内容解压到book文件夹中。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
ReadZipFile.java
import java.io.*;
49
import java.util.zip.*;
public class ReadZipFile
{ public static void main(String args[])
{ File f=new File("book.zip");
File dir=new File("Book");
byte b[]=new byte[100];
dir.mkdir();
try
{ ZipInputStream in=new ZipInputStream(new FileInputStream(f));
ZipEntry zipEntry=null;
while((zipEntry=in.getNextEntry())!=null)
{ File file=new File(dir,zipEntry.getName());
FileOutputStream out=new FileOutputStream(file);
int n=-1;
System.out.println(file.getAbsolutePath()+"的内容:");
while((n=in.read(b,0,100))!=-1)
{ String str=new String(b,0,n);
System.out.println(str);
out.write(b,0,n);
}
out.close();
}
in.close();
}
catch(IOException ee)
{
System.out.println(ee);
}
}
}
? 实验后的练习:
1. 编写一个GUI程序,提供1个对话框,用户可以使用这个对话框选择要解压缩的zip文件,设置解压后所得到的文件的存放目录。
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
50
实验八 网络编程
【目的】
①学会使用URL对象;
②学会使用套接字读取服务器端的对象;
③掌握DatagramSocket类的使用。
【内容】
1.读取服务器端文件。
? 实验要求:
创建一个URL对象,然后让URL对象返回输入流,通过该输入流读取URL所包含的资源文件。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
ReadFile.java
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
public class ReadURLSource
{ public static void main(String args[])
{ new NetWin();
}
}
class NetWin extends Frame implements ActionListener,Runnable
{ Button button;
URL url;
TextField text;
TextArea area;
byte b[]=new byte[118];
Thread thread;
NetWin()
{ text=new TextField(20);
area=new TextArea(12,12);
button=new Button("确定");
button.addActionListener(this);
thread=new Thread(this);
Panel p=new Panel();
p.add(new Label("输入网址:"));
p.add(text);
p.add(button);
51
add(area,BorderLayout.CENTER);
add(p,BorderLayout.NORTH);
setBounds(60,60,360,300);
setVisible(true);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e)
{
if(!(thread.isAlive()))
thread=new Thread(this);
try{
thread.start();
}
catch(Exception ee)
{ text.setText("我正在读取"+url);
}
}
public void run()
{ try { int n=-1;
area.setText(null);
String name=text.getText().trim();
【代码1】 //使用字符串name创建url对象
String hostName=【代码2】 //url调用getHost() int urlPortNumber=【代码3】 //url调用getPort() String fileName=【代码4】 //url调用getFile()
InputStream in=【代码5】 //url调用方法返回一个输入流 area.append("\n主机:"+hostName+"端口:"+urlPortNumber+
"包含的文件名字:"+fileName);
area.append("\n文件的内容如下:");
while((n=in.read(b))!=-1)
{ String s=new String(b,0,n);
area.append(s);
}
}
catch(MalformedURLException e1)
{ text.setText(""+e1);
return;
}
catch(IOException e1)
52
{ text.setText(""+e1);
return;
}
}
? 实验后的练习:
1. public int getDefaultPort()、public String getRef()、public
StringgetProtocol()等方法都是URL对象常有的方法,在模板中让url调用这些方法,并输出这些方法返回的值。
2.使用套接字读取服务器端对象。
? 实验要求:
客户端将服务器端的文本区对象读取到客户端,并添加到窗口中。首先将服务器端的程序编译通过,并运行,等待客户的呼叫。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
客户端模板:Client.java
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class Client extends Frame implements Runnable,ActionListener
{ Button connection;
Socket socket=null;
ObjectInputStream in=null;
ObjectOutputStream out=null;
Thread thread;
public Client()
{ socket=new Socket();
connection=new Button("连接服务器,读取文本区对象");
add(connection,BorderLayout.NORTH);
connection.addActionListener(this);
thread = new Thread(this);
setBounds(100,100,360,310);
setVisible(true);
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
}
public void run()
53
{ while(true)
{ try{ TextArea text=(TextArea)in.readObject();
add(text,BorderLayout.CENTER);
validate();
}
catch(Exception e)
{ break;
}
}
}
public void actionPerformed(ActionEvent e)
{ if(e.getSource()==connection)
{ try
{ if(socket.isConnected())
{
}
else
{ InetAddress address=InetAddress.getByName("127.0.0.1"); InetSocketAddress socketAddress=【代码1】//创建端口为4331、地址为
//address
socketAddress
【代码2】 //socket建立和socketAddress的连接呼叫。
in =new ObjectInputStream(【代码3】); //socket返回输入流 out = new ObjectOutputStream(【代码4】); //socket返回输出流
thread.start();
}
}
catch (Exception ee){}
}
}
public static void main(String args[])
{ Client win=new Client();
}
} 的
服务器端模板:Server.java
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
public class Server
{ public static void main(String args[])
{ ServerSocket server=null;
54
ServerThread thread;
Socket you=null;
while(true)
{ try{ server=【代码1】//创建在端口4331上负责监听的 ServerSocket对象
}
catch(IOException e1)
{ System.out.println("正在监听");
}
try{ you=【代码2】 // server返回和客户端相连接的Socket对象 System.out.println("客户的地址:"+you.getInetAddress()); }
catch (IOException e)
{ System.out.println("正在等待客户");
}
if(you!=null)
{ new ServerThread(you).start();
}
else{ continue;
}
}
}
}
class ServerThread extends Thread
{ Socket socket;
ObjectInputStream in=null;
ObjectOutputStream out=null;
String s=null;
ServerThread(Socket t)
{ socket=t;
try { out=new ObjectOutputStream(【代码3】); //socket返回输出流。 in=new ObjectInputStream(【代码4】); //socket返回输入流。 }
catch (IOException e)
{}
}
public void run()
{ TextArea text=new TextArea("你好,我是服务器",12,12);
try{ out.writeObject(text);
}
catch (IOException e)
{ System.out.println("客户离开");
}
}
55
}
? 实验后的练习:
1. 参照模板程序,编写一个客户/服务器程序,服务器向客户发送一个TextArea对象和一个Button对象。
3.基于UDP的图像传输。
? 实验要求:
编写客户/服务器程序,客户端使用DatagramSocket对象将数据包发送到服务器,请求获取服务器端的图像。服务器端将图像文件包装成数据包,并使用DatagramSocket对象将该数据包发送到客户端。首先将服务器端的程序编译通过,并运行起来,等待客户的请求。
? 程序运行效果示例:
程序运行效果如下图所示:
? 程序模板:
客户端模板:Client.java
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class ImageCanvas extends Canvas
{ Image image=null;
public ImageCanvas()
{ setSize(200,200);
}
public void paint(Graphics g)
{ if(image!=null)
g.drawImage(image,0,0,this);
}
public void setImage(Image image)
{ this.image=image;
}
}
class Client extends Frame implements Runnable,ActionListener
{ Button b=new Button("获取图像");
ImageCanvas canvas;
Client()
{ super("I am a client");
setSize(320,200);
setVisible(true);
b.addActionListener(this);
add(b,BorderLayout.NORTH);
canvas=new ImageCanvas();
56
add(canvas,BorderLayout.CENTER);
Thread thread=new Thread(this);
validate();
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e) { System.exit(0);
}
}
);
thread.start();
}
public void actionPerformed(ActionEvent event)
{ byte b[]="请发图像".trim().getBytes();
try{ InetAddress address=InetAddress.getByName("127.0.0.1");
DatagramPacket data=【代码1】 //创建数据包,该数据包的目标地址和端口分别是
//address和1234,其中的数据为数组b中的全部字节。
DatagramSocket mailSend=【代码2】 //创建负责发送数据的DatagramSocket对象。
【代码3】 // mailSend发送数据data。 }
catch(Exception e){}
}
public void run()
{ DatagramPacket pack=null;
DatagramSocket mailReceive=null;
byte b[]=new byte[8192];
ByteArrayOutputStream out=new ByteArrayOutputStream();
try{ pack=new DatagramPacket(b,b.length);
【代码4】 //创建在端口5678负责收取数据包的DatagramSocket对象。 }
catch(Exception e){}
try{ while(true)
{ mailReceive.receive(pack);
String
String(pack.getData(),0,pack.getLength());
if(message.startsWith("end"))
{ break;
}
out.write(pack.getData(),0,pack.getLength());
}
byte imagebyte[]=out.toByteArray();
out.close(); message=new
57
Toolkit tool=getToolkit();
Image image=tool.createImage(imagebyte);
canvas.setImage(image);
canvas.repaint();
validate();
}
catch(IOException e){}
}
public static void main(String args[])
{ new Client();
}
}
服务器端模板:Server.java
import java.net.*;
import java.io.*;
public class Server
{
public static void main(String args[])
{ DatagramPacket pack=null;
DatagramSocket mailReceive=null;
ServerThread thread;
byte b[]=new byte[8192];
InetAddress address=null;
pack=new DatagramPacket(b,b.length);
while(true)
{ try{ mailReceive=【代码1】//创建在端口1234负责收取数据包的 //DatagramSocket对象。
}
catch(IOException e1)
{ System.out.println("正在等待");
}
try{ mailReceive.receive(pack);
address=【代码2】 //pack返回InetAddress对象。 System.out.println("客户的地址:"+address);
}
catch (IOException e) { }
if(address!=null)
{ new ServerThread(address).start();
}
else
{ continue;
}
}
}
58
}
class ServerThread extends Thread
{ InetAddress address;
DataOutputStream out=null;
DataInputStream in=null;
String s=null;
ServerThread(InetAddress address)
{ this.address=address;
}
public void run()
{ FileInputStream in;
byte b[]=new byte[8192];
try{ in=new FileInputStream ("a.jpg");
int n=-1;
while((n=in.read(b))!=-1)
{ DatagramPacket data=【代码3】 //创建数据包,目标地址和端口
分别是
//address和5678,其中的数据为数组b中
的前n个字节
DatagramSocket mailSend=【代码4】 //创建发送数据的
DatagramSocket对象
【代码5】 // mailSend发送数据data
}
in.close();
byte end[]="end".getBytes();
DatagramPacket data=【代码6】 //创建数据包,目标地址和端口分别
是
//address和5678,其中的数据为数组end
中的全部字节
DatagramSocket mailSend=【代码7】 //创建负责发送数据的
DatagramSocket对象
【代码8】 // mailSend发送数据data
}
catch(Exception e){}
}
}
? 实验后的练习:
1. 将上述模板程序改成用户从服务器获取一个文本文件的内容,并在客户端显示。
【结果】
将本次上机实验结果按照实验要求内容依次进行,填写实验目标、过程、结果。
【注意事项】
59
①实验报告要求每人提交一份,使用专门的报告纸,内容写全,包括实验名称、班级、姓名、同组人,试验日期、交报告日期等。
②报告不需要填写源代码,只要将完成情况和所有练习题结果写上就可以。
【思考题】
60