Effective Java读书笔记十七(Java Tips.Day.17)

来源:互联网 发布:道路工程软件 编辑:程序博客网 时间:2024/06/18 10:34

TIP 45 将局部变量的作用域最小化

最佳方法:在第一次使用局部变量的地方声明。

  • 你无须在方法一开始就声明局部变量,这是一种旧习——你out了。
  • 几乎每个局部变量的声明都应包含一个初始化表达式。
  • try-catch语句块的情况有点特殊。如果一个变量被一个方法初始化,而这个方法可能抛出一个受检的异常(check exception), 那么该变量必须在try块的内部初始化。
  • 在循环中,允许声明一个循环变量,它们的作用域会被限定在循环块内。因此,如果在循环终止之后,不再需要循环变量的内容,那么for循环就优于while循环。
  • 使方法小而集中,同样可以使局部变量的作用域最小化。

TIP 46 for-each循环优先于传统的for循环

在Java 1.5之前,循环优先使用for循环,它优先于while循环。

但是,它们并非完美,无论是迭代器还是索引变量都可能被意外改变,造成混乱和错误。

在1.5之后,加入了for-each循环,成为首选的循环表达方式。

  • 隐藏迭代器或者索引变量可以避免混乱和出错的可能。
  • 自动边界检测。
  • 在嵌套循环中,相比传统循环更有优势。
  • 除了集合,for-each还可以遍历任何实现Iterable接口的对象。如果你在编写的类型表示的是一组元素,即使你不选择让它实现Collection,也要让它实现Iterable接口。这样就允许for-each遍历你的类型,会令用户永远感激不尽的(这句是原文…)。

然而,总会有一些例外情况,不能使用for-each:

  1. 过滤—— 如果需要遍历集合,并删除指定的元素,就需要使用显示的迭代器,以便可以调用它的remove方法。
  2. 转换—— 如果需要遍历列表或者数组,并取代它部分或全部的元素值,就需要列表迭代器或数组索引,以便设定元素的值。
  3. 平行迭代——- 如果要并行地遍历多个集合,就需要显示地控制迭代器或索引变量,以便所有的迭代器或索引变量都可以同步前移。

在这些例外情况下,就需要使用普通的for循环。


TIP 47 了解和使用类库

好处多多。

  1. 通过使用标准类库,可以充分利用这些编写标准类库专家的知识,以及在你之前的其他人的使用经验。
  2. 不必浪费时间为那些与工作不太相关的问题提供特别的解决方案。
  3. 标准类库会有专家维护更新,它们的性能也会随着更新而不断提高。或者,增加新的功能。、
  4. 可以使自己的代码融入主流,更加易于阅读、维护、以及被其它开发人员重用。

有两种工具值得特别一提:

  1. Collection Framework 集合框架。它应该成为每个程序员基本工具箱中的一部分。
  2. Concurrent 并发工具。这个并发工具类库包含了高级的并发工具来简化多线程编程,也包含了低级别的并发基本类型,允许专家们自己编写更高级的并发抽象。这个工具也应该是基本工具箱中的一部分。

总之,不要重复造轮子。


TIP 48 如果需要精确的答案,请避免使用float和double

float和double是为了科学计算和工程计算而设计的,它们执行二进制浮点运算,在广泛的数值范围提供较为精确的快速近似计算。然而,它们并没有提供完全精确的结果。

比如货币运算,因为要让一个float或者double精确的表示0.1,或者10的任何其它负数幂的值,是不可能。
如果你有1.05元,花掉了0.45元,还剩下多少:
System.out.println(1.05 - 0.45);

你希望是0.6,然后实际运行结果是 0.6000000000000001。
或者:
System.out.println(1 - 9 *0.1);

它的运算结果是:0.09999999999999998。

这绝非我们希望的。


使用BigDecimal类可以避免此类问题,然而相比基本类型运算,它们很不方便,而且很慢。

除此之外,还有一种解决办法是使用int或long, 同时要自己处理十进制小数点。
在货币运算中,通常使用最小的货币单位(比如分)来进行计算,避免小数点的使用。


总之,对于任何需要精确答案的计算任务,应避免使用float和double。

如果你想让系统记录小数点,并且不嫌麻烦,就使用BigDecimal,它还可以控制舍入方式。

如果你对性能有需求,所涉及的数值又不大,同时愿意自己管理小数点,就可以使用int。如果不超过18位数字,可以使用long。如果数值可能超过18位,就必须使用BigDecimal。