Java并发编程实践课程习题与答案
Java语言概述
1、Java源程序是由什么组成的?一个程序中必须有public类吗?Java源文件的命名
有什么规定?
2、应用程序和小应用程序的主要区别是什么?
3、开发与运行应用程序需要经过哪些主要步骤和过程?
4、安装JDK之后如何设置JDK系统的PATH,CLASSPATH?他们的作用是什么?
5、Java语言特点是什么?
6、分别用JDK、GEL和Eclipse编写能输出“Hello World!”的Java应用程序。Java面向对象程序设计基础
1、什么是类?什么是对象?对象和类是什么关系?
2、什么是方法?结构方法和一般方法有什么区别?设计方法应考虑哪些因素?
3、为什么要将类进行封装,封装的原则是什么?
4、创建一个有两个方法的类,要求其中第一个方法两次调用第二个方法,第一次不
使用this,第二个使用this。
5、要求设计一个矩形类Rectangle,要求实现构造方法的多态。并利用这些构造方法
实例化不同的对象,并输出相应的信息。
6、计算出Fibinacii 序列的前n项,n的值要求从命令行输入。Fibinacii 序列的
前两项是1,后续每项的值都是该项的前两项之和。即
F(n)=F(n-1)+F(n-2)
F(1)=F(2)=1;
7、什么是继承?什么是父类?什么是子类?继承的特性可给面向对象编程带来什么好处?
什么是单重继承?什么是多重继承?
8、“子类的成员变量和成员方法的数目一定大于等于父类的成员变量和成员方法的数
目”,这种说法是否正确?为什么?
9、什么是方法的覆盖?方法的覆盖与域的隐藏有何不同?与方法的重载有何不同?
10、什么是多态?面向对象程序设计为什么要引人多态的特性?使用多态有什么优点?
11、父类对象与子类对象相互转化的条件是什么?如何实现它们的相互转化?
12、一个类如何实现接口?实现某接口的类是否一定要重载该接口中的所有抽象方法?
13、编写求解几何图形(如直线、三角形,矩型,圆,多边型)的周长,面积的应用
程序,要求用到继承和接口等技术。
14、编写求解一元多次方程(如一元一次,一元二次,一元高次方程)的解。
15、找出以下代码有错误的部分
public int searchAccount(int number[25]){
number =new int[15];
for(int i=0;i number[i]=number[i-1]+number[i+1]; return number; } 16、将一个字符串中的小写字母变成大写字母,并将大写字母变成小写字母. 17、求若干个数的平均数,若干个数从键盘输入. 18、将一个字符串数组按字典序重新排列. 19、编写应用程序,分析字符串,分别输出字符串的单词,并统计出单词个数. 20、编写应用程序,实现字符串“Dot saw I was Tod”的倒转。 21、找出两个字符串中所有共同的字符。 答案 1、J ava程序是由什么组成的?一个程序中必须有public类吗?Java源文件的命名规则是怎样的? 答:一个Java源程序是由若干个类组成。一个Java程序不一定需要有public类:如果源文件中有多个类时,则只能有一个类是public类;如果源文件中只有一个类,则不将该类写成public也将默认它为主类。源文件命名时要求源文件主名应与主类(即用public修饰的类)的类名相同,扩展名为.java。如果没有定义public类,则可以任何一个类名为主文件名,当然这是不主张的,因为它将无法进行被继承使用。另外,对Applet小应用程序来说,其主类必须为public,否则虽然在一些编译编译平台下可以通过(在BlueJ下无法通过)但运行时无法显示结果。 2、怎样区分应用程序和小应用程序?应用程序的主类和小应用程序的主类必须用public修饰吗? 答:Java Application是完整的程序,需要独立的解释器来解释运行;而Java Applet则是嵌在HTML编写的Web页面中的非独立运行程序,由Web浏览器内部包含的Java解释器来解释运行。 在源程序代码中两者的主要区别是:任何一个Java Application应用程序必须有且只有一个main方法,它是整个程序的入口方法;任何一个Applet小应用程序要求程序中有且必须有一个类是系统类Applet的子类,即该类头部分以extends Applet结尾。 应用程序的主类当源文件中只有一个类时不必用public修饰,但当有多于一个类时则主类必须用public修饰。小应用程序的主类在任何时候都需要用public来修饰。 3、开发与运行Java应用程序需要经过哪些主要步骤和过程? 答:主要有三个步骤 (1)、用文字编辑器notepad(或在Jcreator,Gel, BuleJ,Eclipse, Jbuilder等)编写源文件; (2)、使用Java编译器(如Javac.exe)将.java源文件编译成字节码文件.class; (3)、运行Java程序:对应用程序应通过Java解释器(如java.exe)来运行。 4、安装JDK之后如何设置JDK系统的PATH,CLASSPATH?他们的作用是什么? 答、更新系统PATH的方法随Windows版本不同而不同。对于Windows 95/98,可以将下列项目作为C:\autoexec.bat文件的最后一行: SET PATH = d:\jdk1.5.0\bin;%PATH% 当程序需要第三方的类库支持, 而且比较常用, 就可以采用此种方法.比如常用的数据库驱动程序, 写 servlet 需要的 servlet 包等等. 设置方法就是在环境变量中加入 CLASSPATH. 然后就可以直接编译运行了.Java运行环境从CLASSPATH环境变量中寻找要执行的用户项目(三方的类库)。可以按如下的方式设置 SET CLASSPATH=.;d:\jdk1.5.0\jre\lib\rt.jar;%CLASSPATH% 通常我们要从当前目录中寻找用户类,因为开发的程序相关的类放在这里,. 表示当前工作目录. 5、Java语言特点是什么? 答:Java是一种简单的、面象对象的、分布式的、健壮的、安全的、结构中立的、可移植的、性能很优异的多线程的、动态的计算机语言。 6、使用Eclipse编写能输出“Hello World!”的Java应用程序。 答:1) 我们将在 Navigator 中创建一个项目。右键单击 Navigator 视图,然后选择New=>Project。当 New Project 对话框出现时,选择左面的 Java。标准 Eclipse 只有一种 Java 项目类型,名为“Java Project”。选择 Java Project,在提示项目名称时输入“Hello”,然后按 Finish。 右键单击“Hello”项目,选择New=>Class,如图 2 所示。在随后出现的对话框中,键入“Hello”作为类名称。在“Which method stubs would you like to create?”下面,选中“public static void main(String[] args)”复选框,然后按 Finish。 图 2. 在 Java 透视图中创建新类 这样将在编辑器区域创建一个包含 Hello 类和空的 main() 方法的 .java 文件,如图 3 所示。然后向该方法添加如下代码 一旦代码无错误地编译完成,就能够从 Eclipse 菜单上选择 Run 来执行该程序。这时会出现一个具有适当默认设置的 Launch Configurations 对话框;请按右上角的 Run 按钮。一个新的选项卡式窗格将出现在下面的窗格(控制台)中,其中显示了程序的输出。 1、什么是类?什么是对象?对象和类是什么关系? 答:类是抽取了同类对象的共同属性和行为形成的对象或实体的“模板”。 对象是现实世界中实体的描述,是其自身所具有的状态特征及可以对这些状态施加的操作结合在一起所构成的独立实体。 类和对象之间的关系是抽象和具体的关系:类表达的是一种抽象的概念,它描述了该类对象的共同特征;而对象是具体事物,以类为模板来生成,它具有自己的状态。举例:类与对象的关系犹如零件的图纸与按图纸制造出的零件关系一样;图纸(类)描述了零件(对象)的共同特征,每个零件(对象)又有自己的个性,如加工精度的不同等等 2、什么是方法?方法的结构是怎样的?设计方法应考虑哪些因素? 答:方法是Java类的一个组成部分,通过类的方法改变对象的状态。 方法的结构:[方法修饰符] 返回值类型方法名([形参列表])[throws异常列表] { 方法体; } 设计方法应考虑因素有: (1) 方法名是Java中任意的标识符,按照命名的约定,方法名应该是有意义的动词或动词 短语,它的第一个字母一般要小写,其他有意义的单词的首字母要大写,其余字母小写。 (2) 返回值类型可以是任意的Java类型,甚至可以是定义此方法的类。如果方法没有返回 值,则用void表示。 (3) 形式参数列表是可选的。如果方法没有形式参数,就用一对小括号“()”表示。形式参 数列表的形式如下: (类型形参名,类型形参名,……) (4) throws异常列表规定了在方法执行中可能导致的异常。 3、创建一个有两个方法的类,要求其中第一个方法两次调用第二个方法,第一次不 使用this,第二个使用this。 答: class Rectangle //矩形类 { int width; // 矩形的宽 int usethis(int width) //返回宽度的函数 {this. width= width; //指自己这个对象 return width; } int unusethis(int width) { int w=width; return w; } public static void main(String args[]) { Rectangle r=new Rectangle(); //类对象的实例化 System.out.println("It is about the node of this."); //输出语句 System.out.println(https://www.wendangku.net/doc/d01641362.html,ethis(1)); System.out.println(r.unusethis(2)); 运行结果: It is about the node of this. 1 2 4、要求设计一个矩形类Rectangle,其中含有多个构造方法。利用这些构造方法实 例化不同的对象,并输出相应的信息。 答: import java.io.*; class Rectangle //矩形类 { private int width; //矩形的宽度 private int length; //矩形的长度 Rectangle() //矩形的不带参数的构造函数,缺省的给出长(30)和宽(20) { length=30;width=20; } Rectangle(int l,int w) //矩形的带参数的构造函数 { length=l;width=w; } Rectangle(Rectangle r) //此构造方法以另一个Rectangle作为参数 { width=r.width(); //通过对象调用函数并附值给相应变量 length=r.length(); } int width() //返回宽度 { return width; } int length() //返回长度 { return length; } } public class CRctngle { public static void main (String args[ ]) { Rectangle x1=new Rectangle(); //声明类的对象并实例化 Rectangle x2=new Rectangle(50,40); //声明类的对象并初始化 Rectangle x3=new Rectangle(x1); System.out.println(x1.length()); System.out.println(x1.width()); System.out.println(x2.length()); System.out.println(x2.width()); System.out.println(x3.length()); System.out.println(x3.width()); } } 运行结果:30 20 50 40 30 20 体会:此程序中共定义了3个构造方法:Rectangle()、Rectangle(int l,int w) 、Rectangle(Rectangle r) ,其中Rectangle()是没有参数的,Rectangle(int l,int w)以常数作为参数,Rectangle(Rectangle r)是以对象最为参数。构造函数调用时在用new运算符创建类对象是由系统自动完成的,构造函数的参数传递和形实结合也是由系统在调用的同时自动完成。 5、计算出Fibinacii 序列的前10项,Fibinacii 序列的前两项是1,后续每项的值都是 该项的前两项之和。即 F(n)=F(n-1)+F(n-2) F(1)=F(2)=1; 答:class Fibi { public long fibinacii(int n) { long c=0; if(n==1||n==2) c=1; else c=fibinacii(n-1)+fibinacii(n-2); return c; } } public class Example4_5 { public static void main(String args[]) { Fibi a=new Fibi(); for(int i=1;i<=10;i++) { System.out.print(" "+a.fibinacii(i)); } } 6、什么是继承?什么是父类?什么是子类?继承的特性可给面向对象编程带来 什么好处?什么是单重继承?什么是多重继承? 解:继承是面向对象程序设计中两个类之间的一种关系。当一个类获取另一个类中 所有非私有的数据和操作的定义作为它自己的部分或全部成分时,就称这两个类之间具 有继承关系。被继承的类称为父类或超类,继承了父类或超类的所有数据和操作的类称 为子类。 面向对象程序设计中的继承,可使得程序结构更加清晰,降低了编码和维护的工作量。 如果一个类只能有一个父类,则这种继承关系称为单重继承;如果一个类可以有多个 父类,则这种继承关系称为多重继承。 7、“子类的域和方法的数目一定大于等于父类的域和方法的数目”,这种说法是否 正确?为什么? 解:这种说法是错误的,因为子类不一定能继承父类的所有域和方法,它只能继承所 有非私有的域和方法。如果子类在继承之外自己定义的域和方法数目小于父类中私有成 员的数目,则子类的域和方法的数目小于父类的域和方法的数目。 8、什么是方法的覆盖?方法的覆盖与域的隐藏有何不同?与方法的重载有何不同? 解;子类重新定义父类中已经存在的方法,称为方法的覆盖。注意:方法覆盖与域的 隐藏不同。子类重新定义父类已有的域,并不能完全取代它从父类那里继承的同名的域, 这个域仍然占用子类的内存空间,在某些情况下会被使用;而当子类重新定义父类的方法 时,从父类那里继承来的方法将被新方法完全取代,不再在子类的内存空间中占一席 之地。与方法的覆盖不同,重载不是子类对父类同名方法的重新定义,而是在一个类中定义了同名的不同方法。 9、什么是多态?面向对象程序设计为什么要引人多态的特性?使用多态有什么优点? 解:一个类中存在多个同名的方法,称为多态。把抽象功能和目的相同,而具体实现 因不同情况而异的方法命名为同名方法,符合面向对象程序设计中抽象、提升概念,封装、 隐藏细节的特点,从而提高了程序的简洁性和可读性,降低了类和程序模块直接的相互耦 合和依赖。 10、父类对象与子类对象相互转化的条件是什么?如何实现它们的相互转化? 解:一个子类对象也可以被合法地视为一个父类的对象,即一个父类对象的引用,其 指向的内存单元可能实际上是一个子类的对象。在这种情况下,可以使用强制类型转换, 将父类对象的引用转换成实际的子类对象的引用 11、一个类如何实现接口?实现某接口的类是否一定要重载该接口中的所有抽象 方法? 解:使用关键字implements可以定义类实现某接口。实现某接口的类如果不是抽 象类,则需要通过重载来实现该接口中的所有抽象方法;如果这个类是抽象类,则它可以 不必实现该接口中的所有抽象方法。 13、编写求解几何图形(如直线、三角形,矩型,圆,多边型)的周长,面积的应用程序,要求用到继承和接口等技术。 解:// Solution of drawings as triangle,rectangle,circle import java.io.*; // interface interface getProperty { double Pi=3.1415926; double getArea(); double getCircum(); String getName(); } // class mpoint { static int i=0; double x,y; String strmpoint; mpoint(double a,double b) { this.x=a; this.y=b; } double getX(){ return x; } double getY() { return y; } String getString() { i+=1; strmpoint="mpoint"+i; // name of a mpoint; return strmpoint; } } //disp class class disp { double area; double circum; String drawingName; disp(double a, double b, String ss){ this.area=a; this.circum=b; this.drawingName=ss; } System.out.println("Drawing is "+drawingName); System.out.println("Area="+area+"Circum="+circum); } } // class triangle class triangle implements getProperty { mpoint p1,p2,p3; double s1,s2,s3; String drawingName="Triangle"; triangle(mpoint p1,mpoint p2,mpoint p3){ this.p1=p1; this.p2=p2; this.p3=p3; this.s1=Math.sqrt( (p1.x-p2.x)*(p1.x-p2.x)+ (p1.y-p2.y)*(p1.y-p2.y) ); this.s2=Math.sqrt( (p3.x-p2.x)*(p3.x-p2.x)+ (p3.y-p2.y)*(p3.y-p2.y) ); this.s3=Math.sqrt( (p1.x-p3.x)*(p1.x-p3.x)+ (p1.y-p3.y)*(p1.y-p3.y) ); } public double getArea(){ double ss,ssa; ss=(s1+s2+s3)*Pi/2.0/Pi; ssa=Math.sqrt( ss*(ss-s1)*(ss-s2)*(ss-s3) ); return ssa; } public double getCircum(){ return s1+s2+s3; } public String getName(){ return drawingName; } public boolean tline(){ return true; } } // // circle class class circle implements getProperty { mpoint p1; double radius; String drawingName="Circle"; circle(mpoint p1,double radius){ this.p1=p1; this.radius=radius; } public double getArea(){ double ssa; ssa=Math.PI*radius*radius; return ssa; } public double getCircum(){ return Math.PI*2.0*radius; } return drawingName; } public boolean tcircle(){ return true; } } // class rectangle class rectangle implements getProperty { mpoint p1,p2; double s1,s2; String drawingName="Rectangle"; rectangle(mpoint p1,mpoint p2){ this.p1=p1; this.p2=p2; this.s1=Math.sqrt( (p1.x-p2.x)*(p1.x-p2.x) ); this.s2=Math.sqrt( (p1.y-p2.y)*(p1.y-p2.y) ); } public double getArea(){ return s1*s2; } public double getCircum(){ return s1+s2+s1+s2; } public String getName(){ return drawingName; } public boolean rline(){ return true; } } // mainclass class drawing extends disp { drawing(double a, double b, String ss){ super(a,b,ss); } public static void main(String args[])throws IOException { BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in)); String strxx; for(;true;) { System.out.print("Input string like Triangle、Rectangle or Circle:"); strxx=keyin.readLine(); if (strxx.length()==0) continue; char charxx; charxx=strxx.toUpperCase().charAt(0); switch( charxx ) { case 'T': // triangle start // 3point get System.out.println("Please input(triangle) 1 point x(enter)y(enter)"); mpoint p1=new mpoint(aVar(keyin),aVar(keyin)); System.out.println("Please input 2 point x(enter)y(enter)"); mpoint p2=new mpoint(aVar(keyin),aVar(keyin)); System.out.println("Please input 3 point x(enter)y(enter)"); mpoint p3=new mpoint(aVar(keyin),aVar(keyin)); // t1 triangle t1=new triangle(p1,p2,p3); // disp disp tdisp =new disp(t1.getArea(),t1.getCircum(),t1.getName()); tdisp.display(); // mpoint p1=p2=p3=null; // disp tdisp=null; // triangle end break; // ------------------------------------------------------------------- case 'C': // circle start // 1point get System.out.println("Please input(circle) center x(enter)y(enter)"); mpoint p4=new mpoint(aVar(keyin),aVar(keyin)); System.out.println("Please input radius x(enter)"); double radius=aVar(keyin); // t2 circle t2=new circle(p4,radius); // disp disp cdisp =new disp(t2.getArea(),t2.getCircum(),t2.getName()); cdisp.display(); // circle end break; // -------------------------------------------------------------------- case 'R': // rectangle start // 2point get System.out.println("Please input (rectangle)1 point x(enter)y(enter)"); mpoint p6=new mpoint(aVar(keyin),aVar(keyin)); System.out.println("Please input 2 point x(enter)y(enter)"); mpoint p7=new mpoint(aVar(keyin),aVar(keyin)); // t3 rectangle t3=new rectangle(p6,p7); // disp disp rdisp =new disp(t3.getArea(),t3.getCircum(),t3.getName()); rdisp.display(); // circle end break; // ---------------------------------------------------------------------- default: System.out.println("Error! please input t(T),c(C) or r(R);"); } // switch } //endoffor } //main method static double aVar(BufferedReader keyin) throws IOException { // get a double var String xx; xx=keyin.readLine(); return Double.parseDouble(xx); } } 14、找出以下有问题的代码 public int searchAccount(int[25] number){ number =new int[15]; for(int i=0;i number[i]=number[i-1]+number[i+1]; return number; } 解: ①数组的参数说明中不能每含有长度(25)的信息。 ②for循环中,当i=0时,number[i-1]=number[-1];这表示已经越界,并产生数组下标越界例外错误。’ ③return返回语句不是int类型,必须是int[]类型,因为number是数组。 15、将一个字符串中的小写字母变成大写字母,并将大写字母变成小写字母. 解:import java.util.*; public class Ex2{ public static void main(String args[]){ String s=new String("abcABC123"); System.out.println(s); char a[]=s.toCharArray(); for(int i=0;i { if(Character.isLowerCase(a[i])) { a[i]=Character.toUpperCase(a[i]); } else if(Character.isUpperCase(a[i])) { a[i]=Character.toLowerCase(a[i]); } } s=new String(a); System.out.println(s); } } 16、求若干个数的平均数,若干个数从键盘输入. 解:public class Ex3{ public static void main(String args[]){ double n,sum=0.0 ; for(int i=0;i { sum=sum+Double.valueOf(args[i]).doubleValue(); } n=sum/args.length; System.out.println("平均数:"+n); } } 应用程序中的main 方法中的参数args 能接受你从键盘键入的字符串.首先编译上述源程序 D:\>javac Ex3.java 编译通过后,你要使用解释器java.exe来执行你的字节码文件 D:\>java Ex3 "123.78” 23324.9" "213214" (回车) 这时,程序中的args[0],arg[1],arg[2]分别得到字符串"123.78","23324.9" 和"213214". 在源程序中我们再将这些字符串转化为数值进行运算,得到所需的结果. 17、将一个字符串数组按字典序重新排列. 解:class Ex4{ public static void main(String args[]){ String a[]={"boy","apple","Applet","girl","Hat"}; for(int i=0;i {for(int j=i+1;j { if(a[j].compareTo(a[i])<0) { String temp=a[i]; a[i]=a[j]; a[j]=temp; } } } for(int i=0;i { System.out.print(" "+a[i]); } } } 18、编写应用程序,分析字符串,分别输出字符串的单词,并统计出单词个数. 解:import java.util.*; public class Ex5{ public static void main(String args[]){ String s="I am Geng.X.y,she is my girlfriend"; StringTokenizer fenxi=new StringTokenizer(s," "); //空格和逗号做分 int number=fenxi.countTokens(); while(fenxi.hasMoreTokens()) { String str=fenxi.nextToken(); System.out.println(str); System.out.println("还剩"+fenxi.countTokens()+"个单词"); } System.out.println("s共有单词"+number+"个"); } } 19、使用https://www.wendangku.net/doc/d01641362.html,ng 包中System 类的静态方法arraycopy 可以实现数组的快速拷贝 解:class ArrayCopy{ public static void main(String args[]){ char a1[]={'a','b','c','d','e','f'},b1[]={'1','2','3','4','5','6'}; System.arraycopy(a1,0,b1,1,a1.length-1); System.out.println(new String(a1)); System.out.println(new String(b1)); byte a2[]={97,98,99,100,101,102},b2[]={65,67,68, 69, 70, 71}; System.arraycopy(b2,0,a2,3,b2.length-3); System.out.println(new String(a2)); System.out.println(new String(b2)); } } 20、编写应用程序,实现字符串“Dot saw I was Tod”的倒转。解: public class StringsDemo{ public static void main(String[]args){ String palindrome="Dot saw I was Tod"; int len=palindrome.length(); StringBuffer dest=new StringBuffer(len); for(int i=(len-1);i>=0;i--){ dest.append(palindrome.charAt(i)); } System.out.println(dest.toString()); } }