Fork me on GitHub

【读薄Effective Java】通用程序设计

通用程序设计

1.将局部变量作用域最小化

如果过早声明变量,程序员在理解代码的时候可能会记不起来这个变量的初始值了。并且过早声明变量会使作用域变广,可能会在不该被使用的地方被引用。
要把局部变量最小化,最有力的方法就是在第一次使用它的时候声明它
基本上全部局部变量都有初始值,我们需要有初始化所需要的全部信息以后才初始化它。(try catch语句除外)
在这一方面,for循环做的非常好,初始化的循环变量i在合适的位置初始化了,在for结束后i作用域消失。而while循环把变量声明在外,在while结束后,i仍然有效,可能会出复制粘贴bug。
如果把两个操作写到一个方法中,一个操作的局部变量的作用域在另外一个操作里面,可以把原来的一个方法拆成两个方法,每个方法执行一个操作。

2. 如果想要精确的答案,避免使用double和float

我们想知道1.03元花掉0.42元后还有多少钱

#!java
System.out.println(1.03-0.42);
>>0.6100000000000001

很明显答案是有问题的,有时候我们需要讲计算出的数据判断是否相等,这种情况下对答案舍入也没办法接受的。

#!java
BigDecimal a = new BigDecimal("1.03");
BigDecimal b = new BigDecimal("0.42");
System.out.println(a.subtract(b));
>>0.61

这样写虽然很罗嗦而且性能低下,但是还是有一些好处的

  • 获得的数据精确
  • BigDecimal可以完全控制舍入(有8种模式)

3. 优先使用基本类型

我相信没有多少程序员会在代码中到处使用装箱类型,所以只谈论一下基本类型和装箱类型之间需要注意的区别。

  • 基本类型只有值,装箱类型有与值不同的东西,例如Integer从-256到256都是由数组缓存的,在256后都要new一个出来
  • 装箱类型有一个基本类型没有的值null
  • 基本类型比装箱类型更节省空间和时间

3.1 不要在装箱类型上使用==

基本上有在装箱类型上有用到==的情况基本上都是错误的,我们看一下下面的例子

#!java
System.out.println(new Integer(5)==new Integer(5));
>>false

由于没有自动拆箱,并没有提取他们的基本类型的值,而是比较这两个引用是否指向了同一个对象。

3.2 注意装箱类型在类中的初始值

在类中声明基本类型时,初始值默认为0,但是在装箱类型中,初始值默认为null。
下面的代码会抛出空指针错误。

#!java
public class Unbelieable {
    static Integer i;
    public static void main(String[] args) {
        System.out.println(i==0);
    }
}

3.3用到装箱类型的情况

  • 作为集合中的key和value
  • 在泛型中使用
  • 在反射的方法中调用

4. 通过接口引用对象

在声明对象或者方法引用对象的时候,如果有合适的接口选择,我们优先使用接口来声明。例如我们用List接口来代替ArrayList声明列表(这段代码在安卓很常见)

#!java
List<Bean> beans = new ArrayList<>();

使用这种方法声明,当你想换实现方式的时候,比如想用LinkedList代替ArrayList时,只需要改变一个地方即可。从上面可以看出来使用接口引用对象灵活了许多。

posted @ 2018-03-28 00:23  zjmeow  阅读(220)  评论(0编辑  收藏  举报