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可能性较高的条件分支放在前面是不错的做法