Java习题答案太原理工大学软件工程2DOC.docx
《Java习题答案太原理工大学软件工程2DOC.docx》由会员分享,可在线阅读,更多相关《Java习题答案太原理工大学软件工程2DOC.docx(38页珍藏版)》请在冰豆网上搜索。
![Java习题答案太原理工大学软件工程2DOC.docx](https://file1.bdocx.com/fileroot1/2023-2/26/f669e29c-2bc8-45bb-8df3-869b2b307e7b/f669e29c-2bc8-45bb-8df3-869b2b307e7b1.gif)
Java习题答案太原理工大学软件工程2DOC
太原理工大学·Java语言程序设计
(2)
第5章习题解答
1.使用抽象和封装有哪些好处?
答:
抽象是人们解决问题的基本手段,程序设计过程中需要对问题领域进行分析、设计中得出的抽象概念,然后封装成一些类。
封装也称为信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。
系统的其他部分只有通过包裹在数据外面的被授权的操作来与这个抽象数据类型交流与交互。
也就是说,用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象。
把对象中相同或相似地地方抽象出来,从特殊到一半,从具体到抽象的过程,对象经过抽象得到类,类的实例化成了对象。
也可以高度抽象成接口,让不完全相同,但包含相同点的对象实现此接口,也就是利用多态实现。
把相同点抽象出来,抽象成此类或接口的方法、属性、字段等,封装就是隐藏某个对象的与其基本特性没有很大关系的所有详细信息的过程,就是将需要让其他类知道的暴露出来,不需要让其他类了解的全部隐藏起来,封装可以阻止对不需要信息的访问,我们可以使用访问指定符实现封装,也可以使用方法实现封装,可以将隐藏的信息作为参数或者属性值、字段指传给公共的接口或方法,以实现隐藏起来的信息和公开信息的交互。
封装的目的就是为了实现“高内聚,低耦合”。
高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,就是这个类只完成自己的功能,不需要外部参与;低耦合,就是仅暴露很少的方法给外部使用。
2.构造方法的作用是什么?
它与一般的成员方法在使用和定义方面有什么区别?
答:
构造方法用于生成一个对象实例,并对对象实例中的成员变量初始化。
当用new创建一个类的新的对象时,构造方法立即执行。
构造方法名字必须与类名相同。
3.Overload和Override的区别?
答:
方法重载(overloading)与方法覆盖(overriding)是实现多态性的基本手段,但两者的机制不同。
方法重载是指一个类中可以有多个方法具有相同的名字,但这些方法的参数不相同。
参数不同具体体现为:
或者参数的个数不相同,或者是参数的类型不同。
方法覆盖(overriding)是指子类的方法名与父类的方法名完全相同,并且返回值类型、入口参数的数目、类型均相同,即在子类中重新改写了父类的同名方法。
Java根据实际参数的个数和类型来选择调用合适的方法,这样就能使用相同的方法名实现不同的功能,体现了多态性。
4.类、类的成员变量和成员方法的访问权限修饰符分别有哪些?
答:
Java提供public、protected、private、默认等4种访问控制符,在类、成员变量、成员方法的前面可以使用访问控制符关键字,没有显式使用的均为默认控制类型。
Java语言提供的访问权限控制符的访问权限如表5-1。
表5-1Java语言提供的访问权限控制符
本类
本包
不同包中的子类
不同包中的所有类
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)类方法可以通过类直接调用,而不需要创建实例对象。
例如:
JavaApplication的入口main()方法就被声明为static类方法,可以不需要创建任何实例对象对调用。
(2)类方法属于整个类,被调用时可能还没有创建任何对象实例,因此类方法内只可以访问类变量,而不能直接访问实例变量和实例方法。
(3)类方法中不能使用this关键字,因为静态方法不属于任何一个实例。
8.final关键字有何用途?
答:
final可以用来修饰类以及类的成员变量和成员方法。
1.final修饰类
如果一个类被final修饰符修饰和限定,说明这个类称为最终类,它不可能有子类,有子类就意味着可以定义新成员。
JavaAPI中有不少类定义为final类,这些类通常是有固定作用、用来完成某种标准功能的类,例如:
Math类、String类、Integer类等。
abstract和final修饰符不能同时修饰一个类,但是可以各自与其他的修饰符合用。
当一个以上的修饰符修饰类时,这些修饰符之间以空格分开,写在关键字class之前,修饰符之间的先后排列次序对类的性质没有任何影响。
2.final修饰成员变量
用final修饰的成员变量为常量,不允许修改。
同样final修饰符可以与其他修饰符一起修饰成员变量,这些修饰符之间以空格分开,修饰符之间的先后排列次序对成员变量的性质没有任何影响。
3.final修饰成员方法
用final修饰的成员方法是功能和内部语句不能被更改的最终方法,即不能被当前类的子类重新定义的方法。
它固定了这个方法所对应的具体操作,防止子类对父类关键方法的错误重定义,保证了程序的安全性和正确性。
final类中的所有成员变量和方法都被默认为final的。
9.什么是抽象类,如何定义抽象类?
答:
抽象是人们解决问题的基本手段。
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来却不是这样,并不是所有的类都是用来描绘对象的。
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
比如:
进行图形编辑软件的开发时,会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。
正是因为抽象的概念在问题领域没有对应的具体对象,所以用以表征抽象概念的抽象类是不能够实例化的。
抽象类需要使用abstract来修饰,定义语法如下:
abstractclass<类名>[extends<父类>][implements<接口名>]{
<类主体>
}
10.什么是接口,如何定义接口?
答:
接口(interface)是Java所提供的另一种重要功能,它的结构和抽象类非常相似。
接口是一种特殊的类,但接口与类存在着本质的区别。
类有成员变量和成员方法,而接口却只有常量和抽象方法,也就是说接口的成员变量必须初始化,同时接口中的所有方法必须全部声明为abstract方法。
1.接口的定义
通过关键词interface来定义,接口定义的一般形式为
[接口修饰符]interface〈接口名〉[extends〈父类接口列表〉]{
接口体
}
11.接口与抽象类的区别有哪些?
答:
接口和抽象类非常相似。
接口是一种特殊的类,但接口与类存在着本质的区别。
抽象类有成员变量和成员方法,而接口却只有常量和抽象方法。
12.接口是否可继承接口?
答:
与类一样,可以使用extends子句、扩展接口,生成子接口。
原来的接口称为基本接口(baseinterface)或父接口(superinterface),扩展出的接口称为派生接口或子接口。
通过这种机制,派生接口不仅可以保有父接口的成员,同时也可以加入新的成员以满足实际问题的需要。
与类不同的是,一个接口可以扩展多个接口,继承它们所有属性,而一个类只能扩展一个类。
显然,接口不能扩展类,接口的方法必须全是抽象的。
13.java如何实现多重继承?
答:
Java不直接实现多重继承,但是提供了接口实现多重继承。
14.如何定义包和引用包?
答:
使用package定义包,使用import引入包。
15.定义创建一个Rectang1e类,包括两个属性:
weight和height,两个方法:
计算矩形的周长和面积。
importjava.util.*;
publicclassXT_5_15{
publicstaticvoidmain(String[]args){
//TODO自动生成的方法存根
Scanners=newScanner(System.in);
System.out.println("请输入矩形的长和宽,使用空格隔开:
");
doublew=s.nextDouble();
doubleh=s.nextDouble();
Rectangler1=newRectangle(w,h);
System.out.println("矩形的面积为:
"+r1.getArea());
System.out.println("矩形的周长为:
"+r1.getRadius());
}
}
classRectangle{
privatedoubleweight,height;
publicRectangle(doublew,doubleh){
weight=w;
height=h;
}
publicdoublegetArea(){
returnweight*height;
}
publicdoublegetRadius(){
return2*(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方法的测试类,测试复数类的成员方法。
publicclassXT_5_16{
publicstaticvoidmain(String[]args){
complexc1,c2;
c1=newcomplex(2,3);
c2=newcomplex(1,-2);
complex.toString(complex.add(c1,c2));
complex.toString(complex.Multi(c1,c2));
}
}
classcomplex{
privatefloatRealPar,ImaginaryRart;
publiccomplex(floatR,floatI){
this.RealPar=R;
this.ImaginaryRart=I;
}
publiccomplex(){
RealPar=0;
ImaginaryRart=0;
}
publicstaticcomplexadd(complexa,complexb){
complexc=newcomplex();
c.RealPar=a.RealPar+b.RealPar;
c.ImaginaryRart=a.ImaginaryRart+b.ImaginaryRart;
returnc;
}
publicstaticcomplexMulti(complexa,complexb){
complexc=newcomplex();
c.RealPar=(a.RealPar*b.RealPar-a.ImaginaryRart*b.ImaginaryRart);
c.ImaginaryRart=(a.RealPar*b.ImaginaryRart+a.ImaginaryRart
*b.RealPar);
returnc;
}
publicstaticvoidtoString(complexa){
System.out
.println(a.RealPar+"+"+"("+a.ImaginaryRart+")"+"*i");
}
}
第6章习题解答
6.1什么是异常?
为何需要异常处理?
答:
在程序运行时打断正常程序流程的任何不正常的情况称为错误(Error)或异常(Exception)。
在程序设计时,若对程序运行可能出现的错误或异常不进行处理,程序运行发生错误时程序将终止运行,这种处理方法的优点是程序设计比较简单。
但是,对程序错误一概地采用终止运行办法,显然过于简单化,因为有些情况下,完全可以通过其他途径保持程序继续运行。
比如,由于文件名不符合要求而无法打开文件,那么,可以提示用户输入一个新的文件名,从而使程序继续往下运行。
在程序中使用了异常处理,就可以在解决问题之后使程序继续运行,提高了应用程序的健壮性和容错能力。
6.2列举5种常见的异常。
答:
被零除、数组下标越界、引用空对象、文件不能打开、数据格式错误。
6.3Java中的异常处理主要处理哪些类型的异常?
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(ExceptionTypee1){
…
}catch(ExceptionTypee2){
…
}
s4;
⑴语句s3会执行吗?
⑵如果catch捕获到异常,语句s4会执行吗?
⑶如果异常未被捕获,语句s4会执行吗?
答:
若try-catch语句块中的第2个语句s2产生一个异常,⑴语句s3不会执行,⑵如果catch捕获到异常,异常处理后,会继续执行语句s4,⑶如果异常未被捕获,则程序终止运行,语句s4也不会执行。
6.9发生一个异常一定会导致程序终止吗?
答:
发生一个异常不一定会导致程序终止运行。
若程序中没有异常处理,发生一个异常一定会导致程序终止运行。
若程序中有异常处理,发生一个异常并被捕获,则异常处理后,程序会继续运行。
6.10分析下面程序的执行流程并写出输出结果。
//Xt6_10_User_UserException.java
importjava.io.*;
classMyExceptionextendsException{
publicStringtoString(){
return"MyException";
}
}
publicclassXt6_10_UserException{
staticvoidaction()throwsMyException{
Strings=newString();
if(s.equals(""))
thrownewMyException();
}
publicstaticvoidmain(String[]args){
try{
action();
}catch(MyExceptione){
System.out.println(e);
}
}
}
答:
程序运行时,main()方法调用action()方法,action()方法中抛出一个MyException类异常,但没有捕获及处理,而是向上移交给main()方法,在main()方法捕获并处理。
程序执行的输出结果是:
MyException
6.11设计并实现一个程序。
新建一个异常类StringTooLongException,当发现字符串长度太长时抛出该异常。
在程序的main方法中循环输入字符串,直到输入“DONE”为止。
如果输入的字符串长度超过20个字符,则抛出异常。
考虑两种异常处理方式:
⑴抛出异常终止程序;⑵捕获并处理异常,输出适当的提示信息并继续输入字符串。
下面的程序按第2种方式处理。
importjava.util.Scanner;
publicclassXt6_11_DefineException{
publicstaticvoidmain(String[]args){
Stringstr="";
Scannerscan=newScanner(System.in);
StringTooLongExceptionproblem=newStringTooLongException();
do{
System.out.print("输入一个字符串:
");
try{
str=scan.next();
if(str.length()>20)
throwproblem;//抛出自定义异常
}catch(StringTooLongExceptione){
System.out.println(e.toString());
}
}while(!
str.equals("DONE"));
System.out.println("主方法结束.");
}
}
//自定义一个异常类,类名为:
StringTooLongException
classStringTooLongExceptionextendsException{
StringTooLongException(){
super("字符串长度太长!
");
}
}
第7章多线程编程
1.什么是线程?
与进程有何不同?
答:
线程是操作系统中重要概念之一,是程序运行的基本执行单元,与进程一样,也有创建、销毁和切换等状态,但负荷远小于进程,又称为轻量级进程。
与进程不同的是:
占用的资源少,不像进程那样可由几个线程组成,在Java语言中,用java.lang.Thread类创建和管理线程,而进程是由java.lang.Proces