effective Java 系列笔记1

  本系列作为java编程经验的总结,纳入Effective Java目录下,将该书与项目结合,仅做结论性笔记叙述

  比较欣赏本书引言中的一句话:学习编程艺术,首先要学会基本的规则,然后才知道什么时候可以打破这些规则

1、如果类的构造器或者静态工厂中具有多个参数,考虑用Builder模式

参考web开发中的实体类entity引入loombook后使用的注解@Builder

2、避免创建不必要的对象的2个建议

(1)使用静态初始化器

笔者曾经做过一个服务端画图的程序,该程序是为了绘制一张张不同类型的卡片在手机界面分享,这些卡片有些共同点,比如图片的宽度都是相同的,某些区域的颜色或字体是相同的,

再比如类似Calender这样很代价"昂贵"的实例的创建,如果能很好的进行初始化并得以公用,可以很好的提高效率,而不用不断的创建实例

静态初始化器名字很唬人,其实就是我们常见的static静态代码块,我们将某些局部变量提升到类的静态的final域,并在static静态块初始化一次,这种做法将显著提高性能

(2)优先使用基本类型而非装箱基本类型

笔者曾经在这个上面吃过大亏,也是因为正巧碰上一个盲点。拿使用最多的Integer和int举例,我们知道基本类型和对应的装箱基本类型在运算过程中,JVM会自动进行拆箱和装箱操作,这里有个例子

public class Test {
    public static void main(String[] args) {
        Long sum = 0l;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            sum +=1;
        }
        System.out.println(sum);
    }
}

将Long改为long比较一下运行的速度差别,非常显著

第二点:web开发中我们在Controller层接收整数型参数一般用Integer而不是int型,因为Integer可以接收null,但是在比较int型和Integer值得大小时就得注意了

参看下面的程序代码片段一:

public static void main(String[] args) {
    Integer a = 100;
    Integer b = new Integer(100);
    Integer c = Integer.valueOf(100);
    System.out.println(a.equals(b));//true
    System.out.println(a.equals(c));//true
    System.out.println(b.equals(c));//true
    
    System.out.println(a==b);//false
    System.out.println(a==c);//true
    System.out.println(b==c);//false    
}

程序代码片段二:

public static void main(String[] args) {
    Integer a = 127;
    Integer b = 127;
    Integer c = 128;
    Integer d = 128;
    System.out.println(a.equals(b));//true
    System.out.println(a==b);//true
    System.out.println(c.equals(d));//true
    System.out.println(c==d);//false
}

关于Integer学习最好的方法是阅读实现源码,Integer类的equals方法是覆盖了Object的equals,源码中调用的Integer.intValue()做比较,

JVM在启动时会维护8种基本类型的常量池,int类型的常量池维护的范围是-128~127,

因此当执行Integer c = 128时,其实是执行了一个new Integer(128),

我们知道==号比较的是内存地址,连续两个new Integer(128)比较的结果自然是false

笔者当时踩的坑也是一个比较Integer值的位置误用了==,并且本地测试的时候因为id值一般不会超过100,一直找不到原因,而线上id值早已过1000

这里方案有两种,用==号则都用.intValue()的结果做比较,或者直接用equals(),如前所述equals()本身就是调用了intValue()方法,因此要比较值大小直接用equals即可

但是如果是一个int型和Integer作比较,那么Integer类型会自动拆箱和int值作比较,这里免去了很多坑,因此能尽量避免拆装箱错误,以及拆装箱重复操作的,避免之

3、终结方法finalize()方法是不必要的,他和System.gc()一样,只能增加终结方法被执行的机会,但是Java语言规范不仅不保证他们会被及时执行,甚至根本不能保证会被执行

这也不是程序员应该考虑去编写的,jvm的垃圾自动回收现在已经相当成熟,这一点完全不需要程序员再去操心(白操心)

4、在if分支中,将预期true可能性较高的条件分支放在前面是不错的做法



猜你喜欢

转载自www.cnblogs.com/yb38156/p/12394848.html