阿里云藏经阁电子书《Java工程师必读手册》笔记

说明:本文记录一下博主在阅读阿里云藏经阁电子书《Java工程师必读手册》时的笔记,本文中的文字、代码、图片大多来引自该电子书,每个Tips后面附带书中页码,非常建议大家阅读原文。

Tips 1:三元表达式(P25)

boolean condition = false;
Double value1 = 1.0D;
Double value2 = 2.0D;
Double value3 = null;
Double result = condition ? value1 * value2 : value3;

说明:上面的这段代码,最后一行会抛出空指针异常;

分析:因为Java的自动拆箱特性,value1 * value2结果是double,而value3是Double,两者属于是可以转化的类型,故在将value3赋值给result前,会调用value3的doubleValue()方法,就会报NPE


三元表达式类型转化规则如下:

  • 两个表达式类型相同,返回值类型为该类型;
  • 两个表达式类型不同,但类型不可转换,返回值类型为Object类型;
  • 两个表达式类型不同,但类型可以转化,先把包装数据类型转为基本数据类型,然后按照基本数据类型的转化规则(byte < short(char) < int < long < float <double)来转化,返回值类型为优先级最高的基本数据类型。

Tips 2:不能直接返回数据库对象(DO)(P58)

说明:不能直接把数据库查询出来的对象,直接作为结果返回。应该创建一个VO对象,接收所需要的返回结果,作为返回。

原因如下:

• 间接暴露数据库表格设计,给竞争对手竞品分析带来方便;

• 如果数据库查询不做字段限制,会导致接口数据庞大,浪费用户的宝贵流量;

• 如果数据库查询不做字段限制,容易把敏感字段暴露给接口,导致出现数据的安全问题;

• 如果数据库模型类不能满足接口需求,需要在数据库模型类中添加别的字段,导致数据库模型类跟数据库字段不匹配问题;

• 如果没有维护好接口文档,通过阅读代码是无法分辨出数据库模型类中哪些字段是接口使用的,导致代码的可维护性变差。

Tips 3:输入输出参数(P95~96)

说明:有时我们想知道一个参数值,进入函数后,值是否发生变化(发生变化,该参数称为,输入输出参数,Inout Parameter),可以在对应参数前加上final修饰符,然后看编译中哪个参数出现了编译错误,编译错误了的就是输入输出参数,如下:

在这里插入图片描述

Tips 4:Set集合的特性(P118)

说明:通过Set集合无重复元素的特性,可找到集合中重复的第一个元素或去除重复元素

        // 创建一个List
        ArrayList<String> nameList = new ArrayList<>(16);

        // 添加元素
        nameList.add("zhangsan");
        nameList.add("lisi");
        nameList.add("wangwu");
        nameList.add("zhangsan");
        System.out.println(nameList);

        // 1.利用set找到第一个重复的元素
        HashSet<String> nameSet1 = new HashSet<>();
        String firstRepeat = nameList.stream().filter(e -> !nameSet1.add(e)).findFirst().orElse(null);
        System.out.println(firstRepeat);

        // 2.利用set去重
        HashSet<String> nameSet2 = new HashSet<>(nameList);
        System.out.println(nameSet2);

另外,因为Set比较元素是通过HashCode()来实现的,所以如果你需要比较对象,也可自定义对象的HashCode()方法来实现某种目的,如判断用户姓名、性别、出身年月都相同,则判断为同一个人等这样的逻辑。

Tips 5:枚举类的定义(P126)

说明:书中这段对枚举类的说明,非常准确

枚举类型(Enum)是一种特殊数据类型,能够为一个变量定义一组预定义的常量。在使用枚举类型的时候,枚举类型变量取值必须为其预定义的取值之一。

在这里插入图片描述

Tips 6:工具类定义(P144~145)

  • 静态常量,静态(static)在前,常量(final)在后;
  • 工具类使用final定义,避免被继承;
  • 私有化构造方法;

说明:作者不推荐自定义工具类继承Apache工具类,添加自定义的实现方法。因为会不知道调用的常量和方法是Apache工具类提供的,还是自己覆盖重写的。所以推荐直接在工具类上加final关键字,避免继承。一般来说,工具类的方法都会写的很浅,不会有太深的调用关系,限制继承,很合理。JDK中的Objects、Strings都有用final修饰,且构造函数都是私有化的。

在这里插入图片描述


在这里插入图片描述

Tips 7:枚举类定义(P146~147)

  • 删除构造方法多余的private修饰符;
  • 属性类型能用基础类型,就别用包装类;
  • 为了枚举值不被修改,属性用final修饰;

说明:属性类型尽量用基础类型,也是为了避免自动拆箱封箱时的报错;使用final修饰属性,是为了保证枚举值不被修改,万一修改,那代码其他地方有用到的都被改了。

Tips 8:集合定义(P154)

可使用Collections工具类中的unmodifiableCollection()方法,将可变集合对象变为不可变的。

        // 创建一个List
        ArrayList<String> nameList = new ArrayList<>(16);

        // 添加元素
        nameList.add("zhangsan");
        nameList.add("lisi");
        nameList.add("wangwu");
        nameList.add("zhangsan");

        System.out.println(nameList);
        Collection<String> strings = Collections.unmodifiableCollection(nameList);
        strings.add("zhaoliu");// java.lang.UnsupportedOperationException

Tips 9:圈复杂度(P158)

圈复杂度(Cyclomatic complexity,CC)也称为条件复杂度,是一种衡量代码复杂度的标准,其符号为V(G)。

Tips 10:工具类方法使用(P286)

Arrays.asList 返回的 List 并不是 ArrayList,不支持 add 等变更操作。

Tips 11:对象&类(P318~319)

  • 不要用BeanUtils.copyProperties来赋值对象,该工具类方法是用反射实现的,影响性能。
  • 尽量指定指定类的final修饰符

为类指定 final 修饰符,可以让该类不可以被继承。如果指定了一个类为 final,则该类所有的方法都是 final 的,Java 编译器会寻找机会内联所有的 final 方法。内联对于提升 Java 运行效率作用重大,具体可参见 Java 运行期优化,能够使性能平均提高 50%。

注意:使用 Spring 的 AOP 特性时,需要对 Bean 进行动态代理,如果 Bean 类添加了 final修饰,会导致异常。

Tips 12:方法(P320~324)

  • 与类成员变量无关的方法声明成静态方法
  • 尽量使用基本数据类型作为方法形参类型、返回值类型,避免拆线装箱和空指针判断
  • 调用的方法支持传空,调用方无需在调用前再进行空判断;
  • 方法避免不必要的封装(不必要,代码量多还是要装一下的),方法调用会引起入栈和出栈,导致消耗更多的CPU和内存;
  • 尽量指定方法的final修饰符,如类相同,提升Java运行效率;

Tips 13:表达式(P326~328)

  • 尽量减少方法的重复调用,如集合for循环,终止条件不要用list.size(),而是在for循环外定义一个变量存储size(),这样只会调用一次,如下:
        // 创建一个List
        ArrayList<String> nameList = new ArrayList<>(16);

        // 添加元素
        nameList.add("zhangsan");
        nameList.add("lisi");
        nameList.add("wangwu");
        nameList.add("zhangsan");

        // 遍历
        int size = nameList.size();
        for (int i = 0; i < size; i++) {
            System.out.println(nameList.get(i));
        }
  • 避免不必要的方法调用

书中的例子如下:

在这里插入图片描述

  • 尽量使用位运算代替算数运算,如 3 * 4,改为 3 << 2
  • 提取公共表达式,避免重复计算;

书中的例子如下:

在这里插入图片描述

  • 尽量不在条件表达式中用!取反,使用!取反会多一次计算;
  • 多常量选择分支,尽量使用switch,而不是if-else,阈值是5,低于5用if-else,高于5用switch;

Tips 14:字符串(P329、P331)

  • 尽量不要用正则表达式匹配字符串,效率低;
  • 不要用“”+转换字符串,效率低,建议用String.valueOf();

Tips 15:数组(P332、P333)

  • 拷贝数组,尽量用System.arraycopy()或Arrays.copyOf(),不要循环拷贝;
  • 集合转Object数组,直接用toArray(),不用加new Object[0]

Tips 16:集合(P333、P336、P337)

  • 初始化集合时,尽量指定集合大小,避免或减少扩容次数;
  • 不要使用size()方法判断集合为空,必须使用isEmpty()方法;
  • 非随机访问的List,尽量使用迭代代替随机访问;

是否支持随机访问,可往上扒源码,看是否实现RandomAccess接口。但作者接着说,不管支不支持随机访问,都应该使用迭代器进行变量。

在这里插入图片描述

  • 需要频繁调用contains()方法查找数据的场景,可先将List转为HashSet(),List的contains()方法时间复杂度是O(n),HashSet是O(1)

Tips 17:异常(P340)

  • 避免使用异常来控制业务逻辑

书中的例子如下:

在这里插入图片描述

Tips 18:线程(P344~345)

  • 尽量减少同步代码块的范围;
  • 尽量合并为同一同步代码块,如一个循环,循环中调用的方法需要同步,只需在循坏调用的方法上加上同步修饰符集合;

书中的例子如下:

在这里插入图片描述

Tips 19:减少函数代码层级(P357)

函数代码层级保持在1~4之间,过多的缩进会让函数难以阅读。

  • 可使用return,提前返回函数

书中的例子如下:

在这里插入图片描述

Tips 20:封装函数传入参数(P370~371)

  • 参数过多时,需要封装成一个参数类;
  • 当传入成组参数时,应封装为参数类,描述这种现象;
  • 38
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何中应

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值