zoukankan      html  css  js  c++  java
  • 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可能性较高的条件分支放在前面是不错的做法



  • 相关阅读:
    笔试助攻题(思路)
    const 修饰成员函数 前后用法(effective c++ 03)
    UNIX 是啥?!和Linux什么关系?
    我的offer之路(一)
    我的offer之路(一)
    ANSI C 与 K&R C
    c内置数据类型
    预处理器
    小数用二进制如何表示
    C++中有三种创建对象的方法
  • 原文地址:https://www.cnblogs.com/yb38156/p/12394848.html
Copyright © 2011-2022 走看看