《Effective Java》读书笔记七(通用程序设计)

时间:2021-10-19 21:48:36

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

要使局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方声明。

几乎每个局部变量的声明都应该包含一个初始化表达式。如果你还没有足够的信息来对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止。

for循环比while循环好,参考如下两段代码:

有问题的代码,运行时不会得到想要的结果:

Iterator<Element> i = c.iterator();
while(i.hasNext()){
doSomething(i.next());
}
...
Iterator<Element> i2 = c2.iterator();
while(i.hasNext()) { // BUG
doSomethingElse(i2.next());
}

 正确的代码,出现问题立即解决:

for(Iterator<Element> i=c.iterator; i.hasNext()){
doSomething(i.next());
}
... // Compile-time error – cannot find symbol i
for(Iterator<Element> i2=c2.iterator; i.hasNext()){
doSomething(i2.next());
}

No47 了解和使用类库

  • 不要重新发明*,如果你要做的事情看起来是十分常见的,有可能类库中已经有某个类完成了这样的工作。
  • 标准类库的优点:无需关心细节;不必浪费时间;性能有所保证。

建议熟悉掌握如下类库:

java.lang.*;

java.util.*;

java.io.*;

java.sql.*;

java.util.concurrent.*;

No48 如果需要精确的答案,请避免使用float与double

float与double类型主要是为了科学计算和工程计算而设计的。它们执行二进制浮点运算(binary floating-point arithmetic),这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们并没有提供完全精确的结果,所以不应该被用于需要精确结果的场合。

float和double类型尤其不适合于货币计算,因为要让一个float与double精确的表示0.1是不可能的。

除了使用BigDecimal之外,还有一种方法是使用int或者long,到底选用int或者long要取决于所涉及数值的大小。下面代码是使用double/BigDecimal/int计算的例子:

// Avoid float and double if exact answers are required!! - Page 48
import java.math.*; public class Arithmetic {
public static void main(String[] args) {
System.out.println(1.03 - .42);
System.out.println(); System.out.println(1.00 - 9 * .10);
System.out.println(); howManyCandies1();
System.out.println(); howManyCandies2();
System.out.println(); howManyCandies3();
} // Broken - uses floating point for monetary calculation!
public static void howManyCandies1() {
double funds = 1.00;
int itemsBought = 0;
for (double price = .10; funds >= price; price += .10) {
funds -= price;
itemsBought++;
}
System.out.println(itemsBought + " items bought.");
System.out.println("Change: $" + funds);
} public static void howManyCandies2() {
final BigDecimal TEN_CENTS = new BigDecimal( ".10"); int itemsBought = 0;
BigDecimal funds = new BigDecimal("1.00");
for (BigDecimal price = TEN_CENTS;
funds.compareTo(price) >= 0;
price = price.add(TEN_CENTS)) {
itemsBought++;
funds = funds.subtract(price);
}
System.out.println(itemsBought + " items bought.");
System.out.println("Money left over: $" + funds);
} public static void howManyCandies3() {
int itemsBought = 0;
int funds = 100;
for (int price = 10; funds >= price; price += 10) {
itemsBought++;
funds -= price;
}
System.out.println(itemsBought + " items bought.");
System.out.println("Money left over: "+ funds + " cents");
}
}

输出:

0.6100000000000001

0.09999999999999998

3 items bought. Change: $0.3999999999999999

4 items bought. Money left over: $0.00

4 items bought. Money left over: 0 cents

No56 遵守普遍接受的命名惯例

表56 字面惯例的例子

标识符类型

例子

com.google.inject

类或者接口

Timer,FutureTask

方法或者域

remove,ensureCapacity

常量域

MIN_VALUE,NEGATIVE_INFINITY

局部变量

i,xref,houseNumber

类型参数

T,E,K,V,X,T1,T2

  1. 执行某个动作方法通常用动词或者动词短语来命名。如:append或drawImage。
  2. 对于返回boolean值的方法,其名称往往以单词“is”开头。
  3. 如果方法返回被调用对象的一个非boolean的函数或属性,它通常用名词、名词短语,或者以动词“get”开头的动词短语来命名。例如:size、hashCode或者getTime。