Effective Java(2nd Edition) Item 47 学习与使用类库(译文)

设你要生成一个在零与某个上限之间的随机整数。面对这种通用问题,许多程序员会写出大致如下面的小方法:

 

private static final Random rnd = new Random();

// Common but deeply flawed

static int random(int n) {

       return Math.abs(rnd.nextInt()) % n;

}

 

       这段程序看上去蛮好,但有三个瑕疵,首先,如果n2的幂,且较小,则在较短的时段后,产生的随机数会重复。其次,如果n不是2的幂,则平均来看,有些数出现的次数比另一些数更多。如果n是一个大数,就能确定这个效果。下面这段程序可以清楚地说明这一点,这段程序仔细选择了一个范围,在这个范围内生成一百万个随机数,然后打印落在小一半范围的随机数的个数。

 

public static void main(String[] args) {

       int n = 2 * (Integer.MAX_VALUE / 3);

       int low = 0;

       for (int i = 0; i < 1000000; i++)

              if (random(n) < n/2)

                    low++;

       System.out.println(low);

}

 

       如果随机数方法工作正常,程序所打印的数就应接近一百万的一半,但如果你运行这段程序,你就会发现这个数接近666,666。也就是说随机方法所生成数的2/3落在所给范围的低半区。

       上面随机方法的第三个不足是,在一些极罕见的情形,会返回一个不在给定范围内的数,以至运行时出现灾难性的失败。之所以如此,可能是因为这个方法试图将rnd.nextInt()方法返回的值通过方法Math.abs转变成非负的int数,如果nextInt()返回Integer.MIN_VALUEMath.abs也将返回Integer.MIN_VALUE,如果n不是2的幂,则取模(%)操作会返回负数。这将导致你的程序运行失败,而这种错误将很难再现。

 

       要写一个修改了这三个暇疵的random方法的新版本,你得有许多关于伪随机数生成、数字理论及两个补数算法的知识。幸运的是,你不是非这样不可-因为这个方法已实现好了。这个方法称为Random.nextInt(int),从版本1.2开始已是Java平台的一部分。

 

       你不必关心nextInt(int)的详细的实现细节(如果你好奇,你也可以研究它的文档与源代码)。具有算法背景的资深工程师已花了大量时间设计、实现与测试了这个方法,并交给这个领域的若干专家以确认它是正确的。然后类库进行beta测试、发布,数十年来被数以万计的程序员使用。没有得到这个方法的暇疵报告,就算有也会在下个版本中被修证。使用类库,你就利用了实现类库的专家的知识,取得了先于你使用类库的人的经验

 

       使用类库的第二个好处是,不必将你的时间浪费在与你工作基本无关的问题上。与大多数程序员一样,你应该将你的时间放在你的应用研发上,而不是“地下管道”上。

       使用类库的第三个好处是,无需你的努力,标准类库的性能会随着时间的推迟而改善。因为类库被许多人使用,也因为类库以工作标准基准被使用,所以类库的供应商有着强烈的动机让类库运行得更快。多年来,Java平台类库中的大部分已被重写,有些还多次被重写,从而大大提升了性能。

       随着时间的流逝,类库还会增加新功能。如果类库缺少某项功能,开发社团会公开所缺少的功能,该项功能就可能会加在下一个版本中。Java平台从社区中获得了丰富的信息,得到了发展。

       使用类库的最后一个好处是,你置你的代码于主流中,这种类码更易读,易维护,且可以为大多数开发者重用。

       既然使用类库有这么多优势,哪么使用标准类库提供的设施,而不是选择特别的实现,就应是合情合理的。然而仍然有相当部分的开发者不这样做。为什么呢?或许是因为他们不知道类库中存在着这些设施。发布每个主要版本时,许多新的特性都被加入类库中,必须注意并跟踪所加入的特性,每当Java平台有一个新的重要版本,Sun都会发布一个Web 页面以描述新特性。这些页面[Java5-feat, Java6-feat] 是值得阅读的,虽然类库太大以至不太可能研究所有文档[JavaSE6]但每个程序员都应熟悉java.langjava.util中的内容,以及java.io中的一些内容。其它类库中的内容可在需要时再去熟悉。

       总结类库中的内容超出了本条目的范围,但有两点特别值得一提。在1.2版本中,集合框架加入了java.util包。这应该是每个程序员的基本工具箱。集合框架是表示和管理集合的统一设施。允许对集合的操作独立于其表示的细节。它减少了程序员的努力,提高了性能。它还允许无关API间的互操作,减少了设计与学习新API时的困难,提高了软件复用。如果你想作更多的了解,可参见Sun网站的文档[Collections],或学习教程[Bloch06]

       1.5版本中,在包java.util.concurrent中加入了并发工具集。这个包既包含了高层的并发工具以简化多线程编程,也包含了低层次的并发基础原语以便专家实现自已的高层并发抽象。Java.util.concurrent中的高层部分也应该成为每个程序员的基础工具箱(Item 68,Item 69)。

       类库偶尔也有可能不能满足你的需求,如果你的需求越特殊,这种可能性越大。你的第一反应仍是打算使用类库,如果你仔细研究了类库在相同领域提供的功能,并且的确不满足你的需求,再去选择另一种实现。在有限的类库中总归会有功能空洞。如果没有你需要的功能,也就只能你自已去实现了。

       总之,不要发明新的轮子。如果你想做的事是大致公共的,或许类库中已有了一个类是你所需的。如果有,就用它;如果不知道有没有,就查查。一般说来,类库中的代码要比你自已写的好得多,而且会随时改进。这并不是质疑你作为程序员的能力。事实表明,与大部分程序员相比,实现相同功能的类库的代码会获得更多的注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值