Java习题答案 - 太原理工大学软件工程(2)

更新时间:2023-12-31 02:15:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

太原理工大学·Java语言程序设计(2)

第5章 习题解答

1. 使用抽象和封装有哪些好处?

答:抽象是人们解决问题的基本手段,程序设计过程中需要对问题领域进行分析、设计中得出的抽象概

念,然后封装成一些类。封装也称为信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。系统的其他部分只有通过包裹在数据外面的被授权的操作来与这个抽象数据类型交流与交互。也就是说,用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象。把对象中相同或相似地地方抽象出来,从特殊到一半,从具体到抽象的过程,对象经过抽象得到类,类的实例化成了对象。也可以高度抽象成接口,让不完全相同,但包含相同点的对象实现此接口,也就是利用多态实现。把相同点抽象出来,抽象成此类或接口的方法、属性、字段等,封装就是隐藏某个对象的与其基本特性没有很大关系的所有详细信息的过程,就是将需要让其他类知道的暴露出来,不需要让其他类了解的全部隐藏起来,封装可以阻止对不需要信息的访问,我们可以使用访问指定符实现封装,也可以使用方法实现封装,可以将隐藏的信息作为参数或者属性值、字段指传给公共的接口或方法,以实现隐藏起来的信息和公开信息的交互。封装的目的就是为了实现“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,就是这个类只完成自己的功能,不需要外部参与;低耦合,就是仅暴露很少的方法给外部使用。 2. 构造方法的作用是什么?它与一般的成员方法在使用和定义方面有什么区别?

答:构造方法用于生成一个对象实例,并对对象实例中的成员变量初始化。当用new创建一个类的新

的对象时,构造方法立即执行。构造方法名字必须与类名相同。 3. Overload和Override的区别?

答:方法重载(overloading)与方法覆盖(overriding)是实现多态性的基本手段,但两者的机制不同。

方法重载是指一个类中可以有多个方法具有相同的名字,但这些方法的参数不相同。参数不同具体体现为:或者参数的个数不相同,或者是参数的类型不同。方法覆盖(overriding)是指子类的方法名与父类的方法名完全相同,并且返回值类型、入口参数的数目、类型均相同,即在子类中重新改写了父类的同名方法。Java根据实际参数的个数和类型来选择调用合适的方法,这样就能使用相同的方法名实现不同的功能,体现了多态性。

4. 类、类的成员变量和成员方法的访问权限修饰符分别有哪些?

答:Java提供public、protected、private、默认等4种访问控制符,在类、成员变量、成员方法的前面

可以使用访问控制符关键字,没有显式使用的均为默认控制类型。Java语言提供的访问权限控制符的访

问权限如表5-1。

表5-1 Java语言提供的访问权限控制符

private 默认 protected public

5. this、super关键字有何用途?

本类 √ √ √ √ 本包 √ √ √ 不同包中的子类 √ √ 不同包中的所有类 √ 答:子类在继承父类时,可能会出现变量隐藏、方法覆盖(overriding)等现象。变量隐藏指子类的成

员变量与父类成员同名,此时,父类的成员变量被隐藏。方法覆盖指子类的方法与父类的方法名相同,方法的返回值类型、入口参数的数目、类型、顺序均相同,只是方法实现的功能不同,此时父类的方法被覆盖。如果子类需要调用或访问父类被隐藏的变量或被覆盖的方法,可以使用super关键字实现。Java提供关键字super来实现对父类的成员和方法的访问。Super有三种情况可以使用:

⑴ 用来访问父类中被覆盖的方法; ⑵ 用来访问父类中被隐藏的成员变量; ⑶ 用来调用父类中的构造方法。

关键字this可以出现在类的构造方法和非static修饰的成员方法(即实例方法)中,代表实例对象自身,有以下几种使用情况:

(1)在类的成员方法中,可以通过this来访问实例对象的成员变量或调用成员方法。 (2)在类的成员方法中,区分成员变量和局部变量; (3)在类的成员方法中,使用this返回实例对象本身的引用; (4)在类的构造方法中,使用this调用该类的其他构造方法。 6. JAVA实现多态的机制有哪些?

答:多态性包含编译时的多态性、运行时的多态性两大类,即:多态性也分静态多态性和动态多态性

两种。静态多态性是指定义在一个类或一个函数中的同名函数,它们根据参数表(类型以及个数)区别语义,。动态多态性是指定义在一个类层次的不同类中的重载函数,它们一般具有相同的函数,因此要根据指针指向的对象所在类来区别语义,它通过动态联编实现。 Java从多个方面支持多态性,一方面可以通过方法重载实现多态,另一方面也可以通过继承过程中出现的方法覆盖以及对象类型转换(父类引用指向子类对象)实现。方法重载(overloading)与方法覆盖(overriding)是实现多态性的基本手段。 7. 什么是类变量和类方法?

答:static可以用来修饰类的成员变量或成员方法,分别称为类变量(或静态变量)和类方法(或静态

方法)。相应地,没有被static修饰的类的成员变量或成员方法称为实例变量或实例方法。 1.类变量

在生成每个类的实例变量时,Java运行系统为每个对象的实例变量分配一个内存空间,实例变量指向该内存空间,不同的实例变量占用不同的内存区域。对于类变量来说,Java运行系统为类的类变量分配公共的存储空间,该类的每个实例对象共享同一类变量的存储空间。因此,每个对象对类变量的修改都会影响其他实例对象。

类变量可以通过类名直接访问,也可以通过实例对象来访问,都是对同一内存单元的操作, 类变量的使用具有如下特点:

(1)类变量可以通过类名直接访问,而不需要创建对象

(2)任何一个对象对类变量的修改,都是在同一内存单元上完成的。因此,每个对象对类变量的修改都会影响其他实例对象。

2.类方法

声明为static的方法称为类方法(或称静态方法),与此相对,没有static修饰的成员方法则为实例方法。类方法的本质是该方法属于整个类,而不是属于某个实例,可以不创建实例,直接通过类名调用。

类方法的使用具有以下特点:

(1)类方法可以通过类直接调用,而不需要创建实例对象。例如:Java Application的入口main()方法就被声明为static类方法,可以不需要创建任何实例对象对调用。

(2)类方法属于整个类,被调用时可能还没有创建任何对象实例,因此类方法内只可以访问类变量,而不能直接访问实例变量和实例方法。

(3)类方法中不能使用this关键字,因为静态方法不属于任何一个实例。 8. final关键字有何用途?

答:final可以用来修饰类以及类的成员变量和成员方法。

1.final修饰类

如果一个类被final修饰符修饰和限定,说明这个类称为最终类,它不可能有子类,有子类就意味着可以定义新成员。Java API中有不少类定义为final类,这些类通常是有固定作用、用来完成某种标准功能的类,例如:Math类、String类、Integer类等。

abstract和final修饰符不能同时修饰一个类,但是可以各自与其他的修饰符合用。当一个以上的修饰符修饰类时,这些修饰符之间以空格分开,写在关键字class之前,修饰符之间的先后排列次序对类的性质没有任

何影响。

2.final修饰成员变量

用final修饰的成员变量为常量,不允许修改。

同样final修饰符可以与其他修饰符一起修饰成员变量,这些修饰符之间以空格分开,修饰符之间的先后排列次序对成员变量的性质没有任何影响。

3. final修饰成员方法

用final修饰的成员方法是功能和内部语句不能被更改的最终方法,即不能被当前类的子类重新定义的方法。它固定了这个方法所对应的具体操作,防止子类对父类关键方法的错误重定义,保证了程序的安全性和正确性。

final类中的所有成员变量和方法都被默认为final的。 9. 什么是抽象类,如何定义抽象类?

答:抽象是人们解决问题的基本手段。在面向对象的概念中,所有的对象都是通过类来描绘的,但是

反过来却不是这样,并不是所有的类都是用来描绘对象的。如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:进行图形编辑软件的开发时,会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体对象,所以用以表征抽象概念的抽象类是不能够实例化的。 抽象类需要使用abstract来修饰,定义语法如下:

abstract class <类名> [extends<父类>][implements<接口名>]{ <类主体> }

10. 什么是接口,如何定义接口?

答:接口(interface)是Java所提供的另一种重要功能,它的结构和抽象类非常相似。接口是一种特殊

的类,但接口与类存在着本质的区别。类有成员变量和成员方法,而接口却只有常量和抽象方法,也就是说接口的成员变量必须初始化,同时接口中的所有方法必须全部声明为abstract方法。 1.接口的定义

通过关键词interface来定义,接口定义的一般形式为

[接口修饰符] interface〈接口名〉[extends〈父类接口列表〉] {

接口体 }

11. 接口与抽象类的区别有哪些?

答:接口和抽象类非常相似。接口是一种特殊的类,但接口与类存在着本质的区别。抽象类有成员变

量和成员方法,而接口却只有常量和抽象方法。 12. 接口是否可继承接口?

答:与类一样,可以使用extends子句、扩展接口,生成子接口。原来的接口称为基本接口(base interface)

或父接口(super interface),扩展出的接口称为派生接口或子接口。通过这种机制,派生接口不仅可以保有父接口的成员,同时也可以加入新的成员以满足实际问题的需要。与类不同的是,一个接口可以扩展多个接口,继承它们所有属性,而一个类只能扩展一个类。显然,接口不能扩展类,接口的方法必须全是抽象的。

13. java如何实现多重继承?

答:Java不直接实现多重继承,但是提供了接口实现多重继承。

14. 如何定义包和引用包?

答:使用package定义包,使用import引入包。

15. 定义创建一个Rectang1e类,包括两个属性:weight和height,两个方法:计算矩形的周长和面积。

import java.util.*; public class XT_5_15 { }

class Rectangle{

private double weight,height;

public Rectangle(double w,double h){ }

public double getArea(){

return weight*height; weight=w; height=h;

public static void main(String[] args) {

// TODO 自动生成的方法存根

Scanner s=new Scanner(System.in);

System.out.println(\请输入矩形的长和宽,使用空格隔开:\); double w=s.nextDouble(); double h=s.nextDouble();

Rectangle r1=new Rectangle(w,h);

System.out.println(\矩形的面积为:\+r1.getArea());

System.out.println(\矩形的周长为:\+r1.getRadius()); }

}

}

public double getRadius(){ }

return 2*(weight+height);

16. 编写一个完整的Java程序——复数类Complex,使两个复数相加产生一个新的复数(如: 1+2i 和

3+4i 相加的结果为4+6i)。复数类Complex必须满足如下要求: (1)复数类Complex 的属性有: realPart : int型,代表复数的实数部分 imaginPart : int型,代表复数的虚数部分 (2)复数类Complex 的方法有: 构造方法一:将复数的实部和虚部都置0

构造方法二:形参 r 为实部的初值,i为虚部的初值。

complexAdd方法: 将当前复数对象与形参复数对象相加,所得的结果仍是一个复数值,返回给此方法的调用者。

toString( ) 方法: 把当前复数对象的实部、虚部组合成 a+bi 的字符串形式,其中a和b分别为实部和虚部的数据。

(3)完成包含main方法的测试类,测试复数类的成员方法。

public class XT_5_16 { }

class complex {

public complex() { }

RealPar = 0; ImaginaryRart = 0;

private float RealPar, ImaginaryRart; public complex(float R, float I) { }

this.RealPar = R; this.ImaginaryRart = I;

public static void main(String[] args) { }

complex c1, c2;

c1 = new complex(2, 3); c2 = new complex(1, -2);

complex.toString(complex.add(c1, c2)); complex.toString(complex.Multi(c1, c2));

}

public static complex add(complex a, complex b) { }

public static complex Multi(complex a, complex b) { }

public static void toString(complex a) { }

System.out

.println(a.RealPar + \ + \ + a.ImaginaryRart + \ +

complex c = new complex();

c.RealPar = (a.RealPar * b.RealPar - a.ImaginaryRart *

c.ImaginaryRart = (a.RealPar * b.ImaginaryRart + a.ImaginaryRart

* b.RealPar);

return c;

complex c = new complex();

c.RealPar = a.RealPar + b.RealPar;

c.ImaginaryRart = a.ImaginaryRart + b.ImaginaryRart; return c;

b.ImaginaryRart);

\);

第6章习题解答

6.1 什么是异常?为何需要异常处理?

答:在程序运行时打断正常程序流程的任何不正常的情况称为错误(Error)或异常(Exception)。在程序设计时,若对程序运行可能出现的错误或异常不进行处理,程序运行发生错误时程序将终止运行,这种处理方法的优点是程序设计比较简单。但是,对程序错误一概地采用终止运行办法,显然过于简单化,因为有些情况下,完全可以通过其他途径保持程序继续运行。比如,由于文件名不符合要求而无法打开文件,那么,可以提示用户输入一个新的文件名,从而使程序继续往下运行。在程序中使用了异常处理,就可以在解决问题之后使程序继续运行,提高了应用程序的健壮性和容错能力。

6.2 列举5种常见的异常。

答:被零除、数组下标越界、引用空对象、文件不能打开、数据格式错误。 6.3 Java中的异常处理主要处理哪些类型的异常?

Java处理的异常分为3种:Error类、RunTimeException类和其它Exception类。 Error类错误与程序本身基本无关,通常由系统进行处理。RuntimeException类异常主要是程序设计或实现问题,可以通过调试程序尽量避免而不是去捕获。有些异常在程序编写时无法预料,如中断异常、文件没有找到异常、无效的URL异常等,是除RunTimeException类异常的其它Exception异常(非运行时异常)。在正常条件下这些异常是不会发生的,什么时候发生也是不可预知的。为了保证程序的健壮性,Java要求必须对可能出现的这类异常进行捕获并处理。

6.4 如果在try程序块中没有发生异常,那么当该程序块执行完后,程序继续执行什么地方的语句?

答:如果一个try程序块中没有发生任何异常,那么就跳过该块的异常处理程序,继续执行最后一个catch块之后的代码。如果有finally程序块的话,就执行finally程序块及其后的语句。

6.5 如果在try程序块中发生了异常,但找不到与之匹配的异常处理程序,会发生什么情况?

答:如果在try程序块中发生了异常,但找不到与之匹配的异常处理程序,可能会发生2种情况。一种是程序终止运行,一种是把异常向上移交给调用包含该try程序块方法的方法

来处理。

6.6 在try程序块中发生了异常,其后如果有多个catch参数类与之匹配,会执行那个catch块中的异常处理程序。

答:当try语句块中的代码执行时发生异常,程序的正常运行便中断,并抛出异常对象,然后在try块后面的各个catch()中查找与异常对象相匹配的异常类,当找到第一个与之相匹配的参数类时,就执行包含这一参数类的catch语句块中的代码。

6.7 什么情况下要使用finally程序块?

答:finally子句为异常处理提供一个统一的出口,使得在控制流转到其它部分以前(即使有return,break语句),能够对程序的状态作统一的管理。finally程序块中通常都包含一些用于资源释放的代码块。例如,在finally程序块中应将try程序块中打开的所有文件关闭。

6.8 假设下列try-catch语句块中的第2个语句s2产生一个异常,试回答下述问题:

try{

s1; s2; s3;

}catch(ExceptionType e1){

?

}catch(ExceptionType e2){

? } s4;

⑴语句s3会执行吗?

⑵如果catch捕获到异常,语句s4会执行吗? ⑶如果异常未被捕获,语句s4会执行吗?

答:若try-catch语句块中的第2个语句s2产生一个异常,⑴语句s3不会执行,⑵如果catch捕获到异常,异常处理后,会继续执行语句s4,⑶如果异常未被捕获,则程序终止运行,语句s4也不会执行。

6.9 发生一个异常一定会导致程序终止吗?

答:发生一个异常不一定会导致程序终止运行。若程序中没有异常处理,发生一个异常一定会导致程序终止运行。若程序中有异常处理,发生一个异常并被捕获,则异常处理后,程序会继续运行。

6.10 分析下面程序的执行流程并写出输出结果。

//Xt6_10_User_UserException.java import java.io.*;

class MyException extends Exception{ }

public class Xt6_10_UserException { }

答:程序运行时,main()方法调用action()方法,action()方法中抛出一个MyException类异常,但没有捕获及处理,而是向上移交给main()方法,在main()方法捕获并处理。程序执行的输出结果是:MyException

6.11 设计并实现一个程序。新建一个异常类StringTooLongException,当发现字符串长

static void action() throws MyException{ }

public static void main(String[] args) { }

try{

String s=new String(); if(s.equals(\))

throw new MyException();

public String toString(){ }

return \;

action();

}catch(MyException e){ }

System.out.println(e);

度太长时抛出该异常。在程序的main方法中循环输入字符串,直到输入“DONE”为止。如果输入的字符串长度超过20个字符,则抛出异常。考虑两种异常处理方式:⑴抛出异常终止程序;⑵捕获并处理异常,输出适当的提示信息并继续输入字符串。

下面的程序按第2种方式处理。

import java.util.Scanner;

public class Xt6_11_DefineException { }

//自定义一个异常类,类名为:StringTooLongException class StringTooLongException extends Exception{ }

StringTooLongException(){ super(\字符串长度太长!\); }

public static void main(String[] args) {

String str=\;

Scanner scan=new Scanner(System.in);

StringTooLongException problem=new StringTooLongException(); do{

System.out.print(\输入一个字符串:\); try{

str=scan.next(); if(str.length()>20)

throw problem; //抛出自定义异常 }catch(StringTooLongException e){ }

System.out.println(e.toString());

}while(!str.equals(\));

System.out.println(\主方法结束.\); }

第7章 多线程编程

1. 什么是线程?与进程有何不同?

答:线程是操作系统中重要概念之一,是程序运行的基本执行单元,与进程一样,也有创建、销毁和切换等状态,但负荷远小于进程,又称为轻量级进程。与进程不同的是:占用的资源少,不像进程那样可由几个线程组成,在Java语言中,用java.lang.Thread类创建和管理线程,而进程是由java.lang.Process类等类创建和管理。

2. 使用多线程的优势何在?

答:使用多线程具有很多优势,这主要表现在如下五方面:充分利用CPU资源;简化编程模型;简化异步事件的处理;使GUI程序更有效率;节约成本。 3. 主要的线程状态有哪些?它们之间是如何转换的?

答:线程主要有如下5个状态:New(新)、Runnable(可运行、就绪)、Running(运行)、Blocked(被阻塞、挂起)和Dead(死亡),它们之间转换如下图所示:

等待/阻赛/睡眠获得资源获得/失去cpu资源外部事件或占用cpu时间用完新建启动可运行运行执行完成死亡 4. 简述创建线程的两种方法及各自的步骤。

答:第一种方法是通过继承Thread类编写用户自己的线程类,而后创建实例,步骤为: ?

定义自己的线程类MyThread,并覆盖Thread类的run(),实现所需功能;

? 实例化MyThread类,并用start()方法启动。

第二种方法是通过实现Runnable接口来创建线程,使用Runnable接口创建线程的步骤为: ?

实现Runnable接口,如实现了该接口的类为MyRunnable,并在MyRunnable类的run()方法里编写想让线程执行的代码; ? ?

创建实现了Runnable接口类的实例,如创建MyRunnable类的实例为myRunnable;

创建线程类Thread的实例,并用构造方法Thread(Runnable)将myRunnable赋值给target。

5. 简述sleep()方法的作用,并修改例7.10中休眠部分,体会线程有无休眠的差异。

答:sleep()作为休眠方法,可让线程休眠一段时间,此期间线程不消耗CPU资源。传入参数是休眠的时间,单位为毫秒。

例7.10中休眠部分是AddOneThread类run()方法中的sleep()语句,可注释掉或调整休眠时间来体会运行过程差异。

6. 复习线程同步概念,编写一个读写队列的程序,要求至少包含一个写队列线程和一个读队列线程。 答:Java语言提供了关键字synchronized来实现多个线程的同步,并区分为两种实现方法:一种是方法同步,另一种是对象同步。其中,方法同步是为了防止多线程访问同一方法导致数据崩溃。具体来说,在定义方法时加上关键字synchronized修饰即可,这能保证某一线程在其他任何线程访问这一方法前完成一次执行,即某一线程一旦启动对该方法的访问,其他线程只能等待这个线程执行完这个方法后在访问;对象同步是针对某一数据对象而言的,即synchronized关键字还可以放在对象前面限制访问该对象的一段代码,表示该对象在任何时刻只能由一个线程访问。

编写读写队列的程序提示:多个线程同步除了要用关键字synchronized外,还需要用join()方法确保

线程全部执行完。

7. 深入理解wait()和notify()方法使用,设计一种发生死锁的程序,并修改正确。

答:Java语言的java.lang.Object类提供了wait()、notify()和notifyAll()等三个方法来协调线程间的运行进度关系,实现线程通信的,这些方法用于实现线程间的通信,即某线程执行完后通知另一线程继续工作,或者某一线程运行过程中需要某一资源时可等待另一线程释放出或产生出该资源,例7.11很好地说明了这点,可以参考该例修改,最简单来说,改用wait()地方不用,或放错位置。 8. 试着使用线程组来管理习题6编写的程序。

答:提示:定义2个ThreadGroup对象,分别用于管理写队列线程和读队列线程,并分别将创建的写或读线程放入相应的线程组中,便于管理,主要语句如下:。

ThreadGroup writerGroup=new ThreadGroup(\ThreadGroup readerGroup=new ThreadGroup(\Thread myThread1=new Thread(writerGroup, \Thread myThread2=new Thread(readerGroup, \myThread1.start(); myThread2.start();

第8章 图形用户界面编程

8.1 什么是组件?什么是容器?并说明各自的作用。

答:从实现角度来看,组件(Component)是构成GUI 的基本要素,作用是通过对不同事件的响应来完成和用户的交互或组件之间的交互;容器是能容纳和排列组件的对象,如Applet、Panel(面板)、Frame(窗口)等,作用就是放置组件并控制组件位置。

8.2 叙述AWT和Swing组件的关系,指出Swing组件的优点。

答:Swing是在AWT基础上扩展而来的,提供了非常丰富的组件,远远多于AWT,并且引入了新的概念和性能,这使得基于Swing开发GUI应用程序比直接使用AWT开发更为灵活、方便、效率高,而且能设计出更优美的、感受更好的GUI。Swing是由javax.swing包提供的,主要包括两种类型的组件:顶层容器和轻量级组件。它们都以“J”开头。 8.3 总结JFrame的使用要点,并说明如何实现窗体的正常退出。

答:JFrame类包含很多设置窗体的方法,可以用setTitle(String title)方法设置窗体标题,用setBounds(int x,int y,int width,int height)方法设置窗体显示的位置及大小,用setVisable(Boolean b)方法设置可见与否(默认不可见)。此外,向JFrame添加组件有两种方式:调用getContentPane()方法获得内容面板,而后向其中添加组件,或者创建一个中间容器并将组件添加其中,而后用setContentPane()方法把该中间容器设置为JFrame的内容面板。由于JFrame对象的关闭按钮的默认动作只是将窗体隐藏,所以为了正确关闭窗体,应通过setDefaultCloseOperation(int operation)方法设置关闭按钮的动作。 8.4 总结常用Swing组件使用特点。

答:常用Swing组件使用时,首先要创建对应组件的对象,并放置在容器中,一般来说可用setText(String t)设置其的文本信息,setFont(Font font):设置文本的字体及大小,对于列表类组件还可以用AddItem()等方法加入选项,用getSelectedIndices()以int[]形式获得被选中的所有选项的索引值,具体使用方法可参照例8.6。

8.5 查阅资料,简述三个菜单类组件之间的关系,并编写一个带有文件菜单的GUI程序。

答:菜单相关的类主要有菜单栏类JMenuBar、菜单类JMenu和菜单项类MenuItem,此外,还有单选菜单项类JRadioButtonMenuItem和复选菜单项类JCheckBoxMenuItem以及弹出式菜单类JPopupMenu等。前三者的关系是菜单放置在菜单栏上,菜单由若干个菜单项组成。

提示:带有文件菜单的GUI程序核心代码如下:

… final JFrame frm = new JFrame(\文件菜单\ frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frm.setLayout(null);// 设置为不使用布局管理器 // 创建提示标签用于显示点击菜单的标题 final JLabel lbl = new JLabel(\文件菜单示例\ lbl.setBounds(150, 100, 300, 30); frm.add(lbl); // 创建菜单栏并添加到窗体顶部 JMenuBar mbar = new JMenuBar(); frm.setJMenuBar(mbar); // 创建文件下拉式菜单,并添加到菜单栏 JMenu filemenu = new JMenu(\文件\ mbar.add(filemenu); // 创建菜单项,并添加到文件菜单下 JMenuItem openfileItem = new JMenuItem(\打开文件\ JMenuItem closefileItem = new JMenuItem(\关闭文件\ //JMenuItem exitItem=new JMenuItem(\系统退出\ filemenu.add(openfileItem); filemenu.add(closefileItem); filemenu.add(\系统退出\直接添加菜单项 // 获取到直接添加的菜单项,并注册鼠标动作,输出菜单项标题 final JMenuItem exitItem = filemenu.getItem(2);//2表示第三个菜单项 exitItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { lbl.setText(exitItem.getText()); exitItem.setText(\退出\ } }); …

8.6 简述使用面板的原因,编写一个继承自JPanel的面板类MyPanel。

答: 用面板可以实现对所有组件进行分层管理,即对不同关系的组件采用不同的布局管理方式,使组件的布局更加合理和程序的界面更加美观。

编程提示:编写继承自JPanel的面板类MyPanel时,可在MyPanel类中直接放置上面板要放置的组件,在使用该面板时就可以直接放置在窗体上了,例如可创建一个LoginPanel,上面放上用户名和密码输入框及其文本标签,并添加登录和退出按钮和相关代码。

8.7 对比各种布局管理方式,指出各自的应用场合。

答:常见的布局管理器有边界布局(BorderLayout) 、顺序布局(FlowLayout)、网格布局(GridLayout)和卡片布局(CardLayout)等,还有空布局管理的支持(指不用布局管理器)。其中,各种布局管理方式与适合应用的场合如下:

? 空布局管理是直接定位的方式排列容器中的组件,适合只在某一平台运行的程序采

用;

? 边界布局管理器将容器划分为5个部分:顶部(NORTH)、容器底部(SOUTH)、容器

左侧(WEST)、容器右侧(EAST)和容器中心(CENTER),该方式适合需要将组件控制在一定相对位置的应用;

? 流布局管理器是在一行上排列组件,而当该行没足够的空间时则回行显示,容器大小

改变时,组件将自动重排,该方式适合窗体变化时仍需显示各组件的应用; ? 网格布局管理器是将容器按照用户的设置平均划分成若干个网格,每个网格放置一个

组件或容器,该方式适合组件需要规则排列的应用;

? 卡片布局则将容器分为若干层,将各组件按层放入,就像重叠起来的扑克牌,每次只

能看到第一张,即最上面的一张,该方式适合需要呈现多组界面的应用。

8.8 什么是事件源?什么是监听器?使用Java语言编写GUI程序时,两者分别是什么?

答:事件源是事件发生的场所,通常是各个组件,如被按下的按钮;监听器即事件处理者,是对收到的事件进行处理的程序;而事件是用户对界面的操作,如操作键盘时触发的键盘事件。

8.9 简述常用组件可以处理的事件。

答:常用组件可以处理的事件如下表。 AWT事件源 Swing事件源 Buttion CheckBox MenuItem ScrollBar TextField TextArea Window JButtion JCheckBox JMenuItem JScrollBar JTextField JTextArea JWindow ActionEvent ActionEvent、ItemEvent ActionEvent AdjustmentEvent ActionEvent ActionEvent WindowEvent 产生事件的类型 Component JComponent ComponentEvent、FocusEvent、KeyEvent、MouseEvent 8.10 何谓事件适配器类?使用这种类有何好处?

答:事件适配器类(MouuseMotionAdapter、MouseAdapter和WindowAdapter)实际上是

一些实现了事件监听器接口(事件类对应的接口)类,程序员可以直接使用,而不用实现这些接口,这样做的好处是可以简化代码,即只需要扩展该类并重载所需的方法,而不象实现接口时,需要将大量不需要的方法也一一实现。

8.11 简述GUI编程的注意事项,给出事件处理的基本步骤。

答:编写GUI程序时应注意如下事项:

? 选择合适的顶层容器,即窗体(JWindow)、对话框(JDialog)和结构(JFrame); ? 指定或设计所需的布局管理器,获得容器面板;

? 在容器面板上放入界面元素并为按钮等组件注册事件处理程序,编写相关类。 事件处理的基本步骤是

? 创建某组件对象,并考虑该组件对象相关哪个或哪些事件,如创建按钮对象,

相关的事件是动作事件,即ActionEvent;

? 编写该组件对象的事件处理者类,即实现要处理事件对应的监听器接口,如编

写事件处理者ButtonHandler类,实现ActionEvent对应的ActionListenter接口,具体来说实现了该接口中的void actionPerformed(ActionEvent e)方法,在该方法中加入处理该事件的代码;

? 创建事件处理者类的实例,并调用组件对象的对应该类事件的添加方法来注册

监听器,如调用按钮的addActionListener(ActionListener l)方法添加ButtonHandler类的实例。

8.12 使用Swing组件编写一个学生基本信息录入GUI程序。

答:参考代码如下:

import java.awt.Component; import java.awt.Font; import java.awt.event.*; import javax.swing.*;

public class StudentScore { public static void main(String[] args) { LoginDialog dlg = new LoginDialog(); dlg.setVisible(true);

} }

class MainWindow extends JFrame { // 主窗体类 static JLabel submit;// 回显录入成绩标签 MainWindow() { setTitle(\学生成绩录入系统\ setBounds(400, 200, 200, 120); // setExtendedState(JFrame.MAXIMIZED_BOTH); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); setLayout(null);// 设置为不使用布局管理器 createMenu(); submit = new JLabel(); submit.setBounds(5, 5, 400, 20); add(submit); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { exitSystem(); } }); } void exitSystem() // 处理退出系统事件 { int ret = JOptionPane.showConfirmDialog(this, \退出系统吗?\退出系统吗?\ if (ret == JOptionPane.YES_OPTION) { // dispose(); //不能退出登录对话框,需修改登录对话框中的login()方法。 System.exit(0); } } void createMenu() { // 创建菜单栏并添加到窗体顶部 JMenuBar mbar = new JMenuBar(); setJMenuBar(mbar); // 创建2个下拉式菜单,并添加到菜单栏 JMenu m1 = new JMenu(\系统管理\ JMenu m2 = new JMenu(\成绩管理\ mbar.add(m1); mbar.add(m2);

// 创建菜单项,并添加到相应的菜单下 JMenuItem mi11 = new JMenuItem(\基本信息管理\ JMenuItem mi12 = new JMenuItem(\修改密码\ JMenuItem mi13 = new JMenuItem(\退出系统\ mi11.setEnabled(false); mi12.setEnabled(false); m1.add(mi11); m1.add(mi12); m1.add(mi13); // 为退出系统菜单项添加事件 mi13.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { exitSystem(); } }); JMenuItem mi21 = new JMenuItem(\成绩录入\ JMenuItem mi22 = new JMenuItem(\成绩查询\ mi22.setEnabled(false); m2.add(mi21); m2.add(mi22); // 为成绩录入菜单项添加事件 mi21.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { inputScores(); } }); } void inputScores() {// 录入成绩方法 InputScoresDialog isd = new InputScoresDialog(); isd.setVisible(true); } static void setSubmit(String str) { submit.setText(str); }

}// class MainWindow

class InputScoresDialog extends JDialog {// 录入成绩对话框类 JComboBox name; JTextField maths;

JComboBox english;

InputScoresDialog() { setTitle(\成绩录入\ setBounds(500, 250, 240, 180); setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); setLayout(null); setModal(true); createGUIElements(); }

void createGUIElements() { JLabel namelbl = new JLabel(\姓名:\ namelbl.setBounds(10, 20, 60, 25); add(namelbl); JLabel mathslbl = new JLabel(\数学:\ mathslbl.setBounds(10, 50, 60, 25); add(mathslbl); JLabel englishlbl = new JLabel(\英语:\ englishlbl.setBounds(10, 80, 80, 25); add(englishlbl); name = new JComboBox(); name.setBounds(100, 20, 120, 25); name.addItem(\孙文轩\ name.addItem(\孙文迪\ add(name); maths = new JTextField(); maths.setBounds(100, 50, 120, 25); maths.setText(\ add(maths); String[] ranks = { \优秀\良好\中等\及格\不及格\ english = new JComboBox(ranks); english.setBounds(100, 80, 120, 25); add(english);

JButton submitBtn = new JButton(\提交\submitBtn.setBounds(20, 120, 80, 25); add(submitBtn);

JButton cancelBtn = new JButton(\放弃\cancelBtn.setBounds(130, 120, 80, 25); add(cancelBtn);

// 遍历容器中的所有组件,设置字体

for (int i = 0; i < this.getContentPane().getComponentCount(); i++) {

6.使用对象流读/写对象数据时,要求对象所属的类必须实现哪个接口?

答:使用对象流读/写对象数据时,要求对象所属的类必须实现java.io.Serializable 接口以启用其序列化功能。

7.如何判断一个文件是否已经存在?如何删除一个文件?如何重命名一个文件?可以使用File类来获取一个文件包含的字节数吗?

答:用File类的方法exists()判断一个文件是否已经存在;用File类的方法delete()删除一个文件;用File类的方法renameTo(File dest)重命名一个文件;用File类的方法length()获取一个文件包含的字节数。

8.阅读程序,写出程序的输出结果。

//管道流PipedInputStream和PipedOutputStream应用。 import java.io.*;

public class Xt8_8_PipeDemo { }

答:程序的输出结果是: 97 98

public static void main(String args[])throws Exception{ }

PipedInputStream pis; PipedOutputStream pos; byte b;

pis=new PipedInputStream(); pos=new PipedOutputStream(pis); pos.write('a'); pos.write('b'); b=(byte)pis.read(); System.out.println(b); b=(byte)pis.read(); System.out.println(b);

9.编写一个程序,求2~200之间的素数,并将结果保存在文件prime.dat中。再从该文件中读取内容并在屏幕上显示山来。

答:程序设计如下:

import java.io.*;

public class Xt9_9_PrimeInputOutputStream {

public static void main(String[] args) throws IOException{ } }

int i=2,j;

DataOutputStream output=

new DataOutputStream(new FileOutputStream(\)); output.writeInt(i); for(i=3;i<200;i+=2){ }

output.close();

DataInputStream input=

new DataInputStream(new FileInputStream(\)); while(input.available()>0){ }

input.close();

i=input.readInt();

System.out.print(i+\); for(j=2;j<=i/2;j++)

if(i%j==0) break; output.writeInt(i); if(j>i/2)

10.编写一个程序,比较两个文件的内容是否相同。 答:程序设计如下:

import java.io.*;

import java.util.Scanner;

public class Xt9_10_FileCompare {

public static void main(String[] args)throws IOException {

String str1=\,str2=\;

Scanner scan=new Scanner(System.in);

System.out.print(\输入要比较两个文件的文件名:\); str1=scan.next(); str2=scan.next();

if(FileCompare(str1,str2))

System.out.println(\要比较的两个文件内容相同!\); else

System.out.println(\要比较的两个文件内容不同!\);

}

static boolean FileCompare(String filename1,String filename2)throws IOException{ } }

boolean identical;

FileInputStream fis1,fis2;

fis1=new FileInputStream(filename1); //打开文件输入流1 fis2=new FileInputStream(filename2); //打开文件输入流2 while(fis1.available()>0&&fis2.available()>0)

if(fis1.read()!=fis2.read())

break;

if(fis1.available()>0||fis2.available()>0)

identical=false; identical=true;

else

fis1.close(); //关闭文件输入流,即关闭文件 fis2.close(); //关闭文件输入流,即关闭文件 return identical;

11.编写程序从一个文件读前10行并在屏幕上显示出来。如果文件少于10行,就显示所有行。文件名由用户从键盘输入。

答:程序设计如下:

import java.io.*;

import java.util.Scanner;

public class Xt9_11_BuffereStream {

public static void main(String[] args) throws IOException{ } }

String filename=\,str;

Scanner scan=new Scanner(System.in); System.out.print(\输入文件名:\); filename=scan.next();

FileReader fin=new FileReader(filename);//打开文本文件读 BufferedReader bin=new BufferedReader(fin);//字符流转换为缓冲流 int count=0;

while((str=bin.readLine())!=null&&count<10){//从文件读一行字符 }

bin.close();

System.out.println(str); //显示 count++;

本文来源:https://www.bwwdw.com/article/9hmx.html

Top