注:
教师的点评以粗体 + 红色 标出。
Java 面向对象 试题分析
说明:
(1 )考试时间为2 小时。
(2 )除简答题和编程题外,所有答案均可直接写在试卷上。
(3 )简答题和编程题写在试卷后所附的答题纸上,标明题号。
(4 )要求代码书写规范,并添加相应的注释。
(5 )特设卷面整洁分,凡卷面不整洁导致代码及文字难于识别者,扣除5 分。
点评:
虽然再三强调,但仍有同学的试卷乱得一塌糊涂,由于这些同学本身的分数就不高,所以这部分就不扣分了。
我个人认为,如果卷面整洁,说明这个人办事比较有条理,同学们要注意这些细节,有的时候,细节决定成败。
(6 )部分题目没有标准答案,只要言之成理,均可给分。
点评:
没有标准答案不等于允许你乱写。有些同学的回答与题目风马牛不相及,逻辑混乱,反映出他需要加强文字表达能力方面的训练。
*******************************************************************************
一、判断题(正确的描述打钩,错误的打叉,每题 1 分,共 10 分)
1 抽象类中不可以有非抽象的方法。 (错)
2 如果将一个对象强制类型转换为一个不兼容的类型,将引发 NullPointerException
异常。 (错)
3 Java 中 Object 类是最顶层的类。 (对)
4 程序在编译通过以后,仍然可能出现运行时错误和逻辑错误。 (对)
5 可以通过 javac 来运行一个 Java Application 。 (错)
6 可以在子类构造函数中通过 this 关键字调用基类的构造函数。 (错)
7 Java 语言是 IBM 公司设计的一种面向对象程序设计语言。(错)
8 一个 Unicode 字符占 4 个字节。 (错)
9 在循环语句中,使用 continue; 语句可以跳出循环。 (错)
10 在 Java Application 中如果没有定义 main() 方法,则程序不能编译。 (错)
点评:
这 10 道题没什么好说的,都是知识性的题目。
二、简答题(请将答案写到答题纸上,注明题号。每题 3 分,共 30 分)
1 请看以下代码:
package mytest;
public class Main {
public static void main(String[] args) {
System.out.println(new A());
}
}
class A
{
}
Java 在运行上述代码时输出一个很奇异的结果 :
mytest.A@60aeb0
尝试解释一下可能的原因.
点评:
本题的关键在于虽然类 A 没有定义任何方法,但它隐含着从基类 Object 中继承了 toString() 方法。答案必须点出这一结果是执行 toString() 方法得到的。
2 什么叫多态?你是如何理解多态的?请设计一个简单的示例,展示多态的用法。
点评:
几乎所有的 Java 教材都要介绍多态的概念,但只有能用自己的语言说清楚,并能自己设计一个典型实例展示多态特性的,才算是真正弄明白了。
从试卷中发现,不少同学弄混了方法重载与方法覆盖,认为 “方法重载”就是多态。
3 在 Java GUI 程序中,布局管理器是一个很重要的概念。谈谈你对这个概念的理解,并进而回答以下问题:
如果要你开发出一个 Windows 资源管理器( 图 1 ),你将如何应用合适的“布局管理器”来实现其界面?
图 1 Windows 7 中的资源管理器
请指明你在 图 1 中的哪部分应用哪种布局管理器。
点评:
只要认真地看过课本的,大都能回答出什么是布局管理器。但 114 份试卷中,仅有少数几位同学对 Java 如何实现“资源管理器”的 GUI 给出了“靠谱”的回答,这说明绝大多数同学根本就没有认真地动手写过一个 GUI 程序。
4 int 和 Integer 都可以代表一个整数,这两者在使用上有什么区别吗?为什么 JDK 中要设计两个数据类型来表示同一种数据?
5 Java Application 的程序入口点为 main() 函数,其声明如下:
public static void main (String[] args)
请解释一下为何 main() 函数是公有的和静态的?
6 抽象类与接口都不能直接用来创建对象,那么,这两者什么用?彼此之间又有何区别?
你认为在哪种场合应该用抽象类,哪种场合应该用接口?在JDK中你能找到相应的实例吗?如果能找得到,请分析一下JDK的设计者为何将它们设计为“抽象类(或接口)”。
7 如何判断函数构成重载关系?挑出以下函数中不构成重载关系的函数,指明它违反了哪个判断准则。
( 1 ) void myFunc();
( 2 ) int myFunc(int x,int y);
( 3 ) int myFunc(string str, string str2);
( 4 ) string myFunc(int x, int y);
另外,你还记得 JDK 中有哪个类拥有重载的方法吗?列举一两个。
8 Swing 和 AWT 都可以用于设计 GUI (图形用户界面) 程序,这两者有何区别?
你还用过其他的编程语言或开发工具设计GUI程序吗?如果让它们与Java进行对比,你觉得使用Java设计GUI程序的优点在哪,缺点在哪?
点评:
我出这道题目,其目的在于了解一下学生平时是否主动学习其他知识和技术。我得到的结果是: 99% 的学生都回答只用过 MFC ,而 MFC 是他们前继课程 C++ 要学习的内容。
老师不教,学生就不去主动学习,我不好再说什么了。
9 在面向对象程序中,实现代码复用主要有两种方式:继承和组合。
请设计两段示例代码,分别展示出 Java 实现这两种方式的代码框架。
如果在某个实际开发场景中这两种方式都可用,你认为应该优先选择哪一种?原因?
10 各种类型的几何图形都有自己的面积计算公式,但在一个 CAD (计 算机辅助设计)软件中,图形的种类非常多,如果程序需要计算出任何一种图形的面积,最简单的想法是使用条件判断语句根据图形类型来选择相应的计算公式。然 而,这种方法不太好,可能会导致嵌套层次很深的条件判断语句。另外,如果软件要扩充功能以支持新的图形种类,则又不得不修改调用不同公式计算图形面积的代 码。
在学习了面向对象技术之后,你能对上述问题给出一个较好解决方案来吗?
请以计算圆形、矩形和三角形三种几何图形的面积为例,列出关键代码或者绘出 UML 图来展示你的方案。
点评:
这道题绝大多数学生都答得很好,因为书本上有现成的例子。
我出题有点失误,如果换一个书上没有的开发场景,更能考核出学生是否初步掌握了 OOD 的思想。
三 阅读程序题(每题 3 分,共 12 分)
说明:
请仔细阅读左栏的程序代码,将程序运行结果写在“运行结果”一栏。
程序一 public class Test { public static void main (String[] args) { String s1=new String("Hello"); String s2="Hello"; String s3="Hello";
System.out.println(s1==s2); System.out.println(s1.equals(s2));
System.out.println(s2==s3); System.out.println(s2.equals(s3));
String s4=s1; System.out.println(s1==s4); System.out.println(s1.equals(s4)); } } | 运行结果 false true true true true true |
程序二 public class Test { private static void printArray(int[] arr) { for(int i=0;i< arr.length;i++) System.out.print(arr[i]+","); System.out.println("/n"); } private static void changeValue(int value) { value*=2; } private static void changeValue(int[] arr) { for(int i=0;i<arr.length;i++) arr[i]*=2; } public static void main (String[] args) { int[] arr={1,2,3,4,5}; changeValue(arr[0]); printArray(arr); changeValue(arr); printArray(arr); } } | 运行结果
1,2,3,4,5,
2,4,6,8,10,
|
点评:此题考核学生是否理解了对象类型参数与值类型参数的区别,然而还是有相当多的学生认为 changeValue(int value) 个方法的执行结果会更改原始数组中的元素值。
程序三 class MyException extends Exception { public MyException(String message) { super(message); } } public class Test { private static void fun1() throws MyException { throw new MyException("An MyException object is thrown in fun1()."); } private static void fun2() throws MyException { try { fun1(); } catch(NullPointerException ex) { System.out.println("NullPointerException : "+ex.getMessage()); } finally { System.out.println("Go through finally code in fun2()."); } } public static void main (String[] args) { try { fun2(); } catch(MyException ex) { System.out.println("MyException:"+ex.getMessage()); } catch(Exception ex) { System.out.println("Exception:"+ex.getMessage()); } } } |
运行结果 Go through finally code in fun2(). catch MyException object. Message:An MyException object is thrown in fun1(). |
点评:
此题考核学生是否理解了 Java 的异常处理机制。由于课时有限,这部分内容我在课上没有详细介绍,而是要求学生自学,从试卷中看,答题的情况还可以。
四、程序改错题(每题 3 分,共 12 分)
说明:
下述程序中都包含着错误而不能通过编译。请在右栏指出程序错误的原因(可指明行号),并修改程序使其可以通过编译。
程序一 1 public class Main { 2 public static final A Aobj=null; 3 public static void main(String[] args) { 4 Aobj=new A(); 5 } 6 } 7 class A{ 8 } | 更正
(1) 去掉 final (2) 去掉 main() 函数中的赋值语句 , 定义语句改为 : public static final A Aobj=new A();
|
程序二 01 public class Test { 02 public static void main(String[] args) { 03 MyClass obj=new MyClass(); 04 obj.Info+=",World!"; 05 System.out.println(obj.Info); 06 } 07 } 08 class MyClass { 09 public String Info="Hello"; 10 public MyClass(String Info) 11 { 12 this.Info=Info; 13 } 14 } | 更正 尝试调用默认构造函数。但在用户指定了一个构造函数之后,不再允许直接调用默认构造函数。
更正: Test obj=new Test("Hello");
|
程序三 01 abstract class Animal { 02 public abstract void saySomething() { 03 System.out.println(" 你想说什么就说吧! "); 04 } 05 } 06 class Dog extends Animal { 07 public void saySomething() { 08 System.out.println(" 我现在有了第二职业:捉耗子! "); 09 } 10 } 11 public class Test { 12 public static void main (String[] args) { 13 Animal ani=new Dog(); 14 ani.saySomething(); 15 } 16 } | 更正 03句去掉 abstract 。 或者去掉 Animal 类 saySomething 方法中的所有实现代码。
|
六 编程题(共 36 分)
说明:
(1 )编程题共分为两组:简单编程题与综合编程题。简单编程题不要求写出完整的可运行的程序。综合编程题要求写出的程序必须是可以通过编译的完整的程序。
(2 )请在试卷后所附的答题纸上书写程序代码,注明题号。
(3 )代码要书写规范,卷面整洁。
点评:
本次考试的编程题占了 36 分,我的目的是强调动手编程的重要性。这部分题目,如果学生只是看书,能做好是不可能的。
事实证明:多数学生平时根本就不动手,导致大批的题目空白,写的代码语法错误遍地,有的学生甚至写出 C++ 的代码。
1 简单编程题(每题 4 分,共 20 分)
( 1 )编写代码生成 10 个位于 [50,100] 区间的整数。
点评:我本意是要求学生生成随机数,但题目没有强调是随机数,所以,这道题简直就是送分题,难度大大降低。
( 2 )编写一个方法,接收一个整数数组作为参数,此方法会找出其最大值、最小值和平均值。
要求使用递归方法实现。
点评:这道题看上去简单,但其实难度不小。
问题的关键在于如何在方法的递归调用中暂存数据。这有两种方式实现:
第 1 种是将最大值、最小值和平均值作为类的字段,而将求值的递归函数作为类中的方法,在方法的每次递归调用中直接修改类中的相应字段。
第 2 种是创建一个新类,为其设计几个字段来代表最大值、最小值、总和,再提供一个公有方法用于得到平均值,然后将其作为递归函数的一个参数传送。
本题设计时应该将“平均值”改为求“数组元素的总和”,这样可以大大降低本题的难度,这是我设计试题时失误的地方。
本题学生答得很差。
( 3 )如果你设计的一个类只允许创建一个实例,你会如何设计它?写出类的框架代码。
如果希望你设计的类最多只能创建 3 个实例,你又该如何修改你的代码?
再扩充一下:
如果要求你设计一个类,在程序运行时才决定它最多能创建的实例个数,你打算如何设计它?
点评:
这道题学生答得也很差,其实我在讲课时介绍过这个问题。
可以看看我博客上的相关文章:
http://blog.csdn.net/bitfan/archive/2009/12/16/5021214.aspx
虽然是 C# 实现,但同样可用于 Java.
( 4 )为了按内容来比较属于同一类型的两个对象的 “ 大小 ” , JDK 中定义了一个 Comparable 接口用于供程序员自定义两个对象的比较规则,此接口声明如下:
public interface Comparable
{
int compareTo(Object other);
}
实现了此接口的两个对象(不妨称之为 X 和 Y )可以相互比较:两对象 X 和 Y 相等, compareTo() 方法返回 0 , X 小于 Y 时 compareTo() 方法返回一个负数(通常设为- 1 ), X 大于 Y 时返回正数(通常设为 1 )。
请编写一个方法,接收一个 Comparable 对象数组作为参数,然后,此方法对此数组中的对象进行升序排列。
( 5 )从 1 到 100 的 100 个整数,以某种随机的方式进行排列,然将它们挨个放到一个整数数组中,此数组只能容纳 99 个整数,因此,必定会有一个整数会丢弃。
编写一个函数,接收一个包容 99 个整数的数组作为参数,找出被丢弃的哪个整数。
另外,你如何保证此函数接收的数组满足以下预设的条件?
1 )数组包容 99 个整数
2 )数组中的整数均在 [1,100] 的范围之内
3 )数组中不包含两个相同的整数
如果函数接收到的数据不满足上述要求,你打算如何处理?写出你的处理策略。
点评:
这道题其实来自于软件公司的面试题。大多数同学都能顺利地回答第一问,虽然算法不优化。
第 2 问其实是了解一下学生是否知道如何实施 “防卫型”编码,仅有少数学生给出了可行的实现方案。
2 综合编程题( 16 分)
以下为一棵有序二叉树:
图 2
请用 Java 实现上述数据结构,并编写一个函数按前序方式遍历此树的所有节点。
说明:
(1)程序必须为完整的可编译运行的 Java Application 。
(2)假设树中每个节点中都保存着一个整数,代表此节点所保存的数据。
(3)所谓前序遍历,是指从树的根节点开始,先输出根节点保存的数据,然后输出左子树根节点保存的数据,再输出右子树根节点保存的数据,由此不断递归,当访问完树中的所有节点时,遍历完成。
(4)在 main() 函数中编写示例代码创建上图中的二叉树,调用写好的函数,输出前序遍历结果:1,2,3,4,5
(5)请遵循 Java 软件工程师的代码开发规范:在你写的代码中加上注释,并注意变量和类的名字要望名知义,必要的缩进和空行等,让你的代码规范易读。
评分标准:
(1)能以面向对象的思想用 Java 实现“二叉有序树”这一数据结构(6分)
(2)能编写出前序遍历树的函数(6分)
(3)在 main() 中能写出示例代码完成所要求的工作:创建树和输出遍历结果(4分)
点评:
这道题其实就是我讲课PPT中的一个例题,难度很小。然而,至少有一半的学生此题空白,估计主要原因是时间不够。
总结:
本次考试我有意加大了主观题的比重,以强调学生要动手,活学活用知识。
然而,从考试的结果来看,比较严重的问题有以下两点:
1 尽管我多次强调,多数学生仍然习惯于从书本上学编程,结果一遇到“活”一点的题目就不行了。
计算机专业的学生不编程,中文系的学生不写文章……,很遗憾,这种现象在大学中相当普遍,是中国高校的悲哀。
2 学生的主动性不强,很少有主动学习与探索新领域和新技术的。这有很多原因,比如学校设置的必修课过多,占用了学生过多的时间和精力;教师对学生引导不力;课程讲授内容跟不上技术的发展等,学生自身也有原因。
致选修本课的学生:
这次考试的难度并不小,有相当的同学成绩不好,不及格的人数较多。
我需要指出的是:这次考试的难度与不少软件公司的笔试题相比,在考核的技术广度和深度上,都是较低的。考得不好,意味着以你现在的知识和能力,找工作参加面试时,可能也难过软件公司的笔试这一关。
我不是故意为难大家,而是给大家一个提醒。有心的同学,现在应该为未来“未雨绸缪”了。
我原先考虑将本门课的最终成绩定为:闭卷考试成绩+上交的Java大作业水平。
目前作业已收齐,但我还没有细看学生写的程序,有学生反映,大家交来的程序大都是从书上看来,自己作了些修改了,真正是“原创”的不多。
我要先看看这些程序,并将其与考试成绩作个对比判断。因为考虑到分数高低有可能会影响到学生保研和奖学金的评定等现实问题,如果发现大作业的实情真的是上面所说的情况,我会考虑直接以闭卷考试成绩作为本门课程的最终成绩,以尽可能地提供一个公平。
http://blog.csdn.net/bitfan/archive/2009/12/28/5092955.aspx