一道面试题的分析

原创 2006年06月19日 20:02:00

这是我为公司设计的一道Java语言的面试题……嗯……也可以说是两道啦:
写一个Money类,包含金额和币种两个属性,以及加、减两个方法。
附加题:将上题中的Money类实现为一个ValueObject。

先来看本题。

第一个要考察的方面是为两个属性选择正确的数据类型。(不知道什么是属性?……回去换个被程序员更有前途的职业吧。)

对金额而言,最自然的选择是float或者double。但这不是最好的选择。在计算机中,float和double都是有误差的。比如1有可能是1.00000001。所以对金钱这么重要而敏感的东西来说,还是BigDecimal比较好。当然,对于后面的加减运算来说比较麻烦一些。这时还是让人比较怀念C++的运算符重载的。
用int怎么样呢?如果用int来表示以分为单位的金额的话,到也不是不可以。这样精度有保证,而且运算也比较方便。不过如果要表示5厘……就没办法了。

对币种来说,很多人多自然选择了String。不过我以为String不如int,或者short。虽然在Java中,String几乎可以当成基本数据类型使用,但是String毕竟是对象,还是经常要考虑null不null的问题,而且字符串匹配总是不如int(或short)方便和快捷。

到了JDK 1.5的时代,我们又多了一个选择:enum。不过如果是在一个信息系统中,货币种类是可以由用户维护的话,那么enum就不能用了。

除此以外,从OO的角度来说,还有更好的设计吗?有。不过这个问题我留到下一篇讨论。

然后是方法的设计。因为有币种,因此加、减时自然都要考虑同币种的金额才能相加(暂时不考虑汇率换算的问题)。如果币种不相同怎么办?这就是考察的第二个重点: 错误处理。

有不少人使用返回值表示计算的成功与否。比较奇怪的是他们大部分都没有C,C++程序员的经历,不知道是不是学校教育的结果。也有人直接使用System.out.println输出错误信息,这个就更离谱了。

正解应该是使用Exception。偷懒的话,可以使用IllegalArgumentException。如果知道自己定义一个Exception,比如IncompatibleCurrencyException,那如果是我面试,这样的人技术上基本就算过关了。

所以两个方法的原型应该是:

    public void add (Money operand)
    throws IncompatibleCurrencyException
   
    public void subtract (Money operand)
    throws IncopatibleCurrencyExcepiton

如果使用BigDecimal表示金额,那么这里还有一个BigDecimal的加减方法的名称的问题。不过这倒不重要。写程序的时候总有API可以查的。

对于参数是否可以为null,有两种选择。一种是参数为null时,什么也不做。另一种是抛出异常,比如NullPointerException。我认为第二种选择为好。大部分情况下,用null做参数调用add和subtract方法恐怕不是程序员的本意,而是其它程序出错的结果。直接抛出异常有助于及早发现其它部分的错误。

除了属性和加,减方法以外,构造函数以及getter/setter函数虽然没有提到,但作为一个完整的类,还是应该要有的。从健壮性的角度考虑,在构造函数中应该对输入参数有一定判断。比如金额不能为null等。

接下来是附加题。什么是ValueObject。简单说,ValueObject的值(状态)一旦创建以后就不会改变了。所以可以当基本数据类型用。比如Java中的String, BigDecimal, BigInteger都是ValueObject。StringBuffer就不是。

要把Money变成ValueObject,首先不能有setter。构造函数是从类外部设定属性值的唯一途径。
其次,add和subtract方法不能修改this的属性,运算结果要以新的Money对象返回,这样其原型就要变成:

    public Money add (Money operand)
    throws IncompatibleCurrencyException
   
    public Money subtract (Money operand)
    throws IncopatibleCurrencyExcepiton


第三,最好是能重新定义equals和hashCode两个方法。如何重新定义,请看Pearson Education的《Effective Java Programming Language Guide》7,8两章。

遗憾的是,到目前为止能全部达到以上要求的应聘者还没有出现过。更不用说我心中一个非常不现实的奢望了,就是看到一个因聘者首先写下这一行:

public class MoneyTest extends TestCase {

......

对一道面试题的总结与扩展思考(关于一笔画问题的数学分析)

摘要 前几天参加了一个公司的面试,其中被问到了一个题。面试官在纸上画了一个图形(具体图形见下文),问我能不能一笔画出这个图形,要求每条边必须只走一次,并且画的过程中笔不能离开纸。当时我没有试着去...

一道阿里多线程面试题的分析与应对

引言: 通过一道阿里的Java多线程面试题目分析,来深入理解Java线程的状态转变过程。...

对一道面试题的总结与扩展思考(关于一笔画问题的数学分析)

转自:http://www.cnblogs.com/leoo2sk/archive/2010/10/18/1854658.html 摘要 前几天参加了一个公司的面试,其中被问到了一个题...

对一道面试题的总结与扩展思考(关于一笔画问题的数学分析)(转载)

摘要 前几天参加了一个公司的面试,其中被问到了一个题。面试官在纸上画了一个图形(具体图形见下文),问我能不能一笔画出这个图形,要求每条边必须只走一次,并且画的过程中笔不能离开纸。当时我没有试着去画 ...

一道面试题的分析

   在 万仓一黍 的博客中看到了“一道有趣的面试题 ”这篇文章,文中给出了一种解法,仔细想了一下,发现也可以在常数时间复杂度下解决。题目:        某幢大楼有100层。你手里有两颗一模一样的玻...

对一道面试题的总结与扩展思考(关于一笔画问题的数学分析)

摘要 前几天参加了一个公司的面试,其中被问到了一个题。面试官在纸上画了一个图形(具体图形见下文),问我能不能一笔画出这个图形,要求每条边必须只走一次,并且画的过程中笔不能离开纸。当时我没有试着去...

一道亚马逊算法面试题的情景分析

阅读博客的朋友可以观看视频: http://study.163.com/course/courseMain.htm?courseId=1002942008我们聚焦于一道亚马逊的算法面试题,通过分析该...

一道asp.net c#面试题

  • 2009年04月26日 21:08
  • 31KB
  • 下载

一道真正的数据库sql面试题

  • 2010年05月16日 15:53
  • 3KB
  • 下载

白话经典算法系列之十 一道有趣的GOOGLE面试题

微博http://weibo.com/MoreWindows已开通,欢迎关注。最近在微博上看到一道有趣的GOOGLE面试题,见下图:文字版:一个大小为n的数组,里面的数都属于范围[0, n-1],有不...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一道面试题的分析
举报原因:
原因补充:

(最多只允许输入30个字)