专栏首页cwl_Java3分钟快速阅读-《Effective Java》(五)

3分钟快速阅读-《Effective Java》(五)

41.慎用重载

使用重载时有些重载方法并不会根据你想要的方式来进行运行的,编译器会根据自己想要的最简便的方式来运行对应的方法,如下所示

public class CollectionClassFind {

    public static String classFind(List<?> list){
        return "List";
    }
    public static String classFind(Set<?> set){
        return "Set";
    }
    public static String classFind(Collection<?> collection){
        return "Collection";
    }

    public static void main(String[] args) {
        Collection<?>[] collections = {
          new HashSet(),new ArrayList(), new HashMap().values()
        };
        for (Collection collection : collections) {
            System.out.println(classFind(collection));
        }
        //理想结果:List Set Collection
        //实际结果:Collection Collection Collection
    }
}

简而言之,能够重载方法并不意味着应该重载方法.如果一定要进行方法重载,那么就要考虑是否会被编译器所忽略

42.慎用可变参数

当我们需要定义参数数目不定的方法时,可变参数时一种很方便的方式,但是不应该被过度滥用,参数列表不应该只有一个可变参数,避免调用方一个参数也不传导致程序出现问题.应该如下所示,用一个固定参数来进行区分

  • 错误做法
    public static void main(String[] args) {
        int sum = sum();
        System.out.println(sum);
    }
    public static int sum(int... args){
        int sum = 0;
        for (int arg : args) {
            sum += arg;
        }
        return sum;
    }
  • 正确做法
    public static void main(String[] args) {
        int sum = sum(1, 3, 4, 5, 6, 7, 8, 9);
        System.out.println(sum);
    }
    public static int sum(int first,int... args){
        for (int arg : args) {
            first = first + arg;
        }
        return first;
    }

43.返回0长度的数组或者集合,而不是null

如果方法返回集合是抛给一个null,那么就会需要调用方来处理这个问题,此时我们应该尽可能的自己来解决这个异常,以避免给调用者带来不必要的麻烦

  • 错误做法
    private final List<Cheese> cheeses = new ArrayList<>(10);
    public List<Cheese> getCheeses(){
        if(cheeses.size() == 0){
            return null;
        }
        return cheeses;
    }
  • 正确做法
    private final List<Cheese> cheeses = new ArrayList<>(10);
    public List<Cheese> getCheeses(){
        if(cheeses.size() == 0){
            return null;
        }
        return Collections.EMPTY_LIST;
    }

44.为所有导出的API元素编写文档注释

这一条没什么好解释的,需要我们习惯性的去执行即可

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

原文释义:早期程序的设计会要求在方法开始的时候就把所有需要用到的局部变量都进行生命,但是这样会导致程序的可读性降低,最好的做法是当局部变量需要用到的时候去使用它. 其实我觉得如果每个方法都能非常规范的把局部变量的声明写在最前面,这样也是可方便方法的阅读的.但是如果想要真正的提高一个方法的可读性,就需要我们把方法设计的小而集中,这才是解决问题的本质做法

46.foreach循环优先于传统的for循环

使用foreach循环好处是相比于传统for循环并没有性能损耗,并且比较不容易出现BUG或者写错循环次数导致索引越界的问题

  • 以下三种情况无法使用foreach
    • 过滤:需要在集合当中删除选定的元素
    • 转换:需要取代集合当中的某个元素
    • 平行迭代:需要并行的遍历多个集合,需要显示控制迭代器或者索引变量,一遍所有迭代器或者索引变量都可以得到同步前移

47.了解和使用类库

引用原文:不要重新发明轮子,如果你要做的事情看起来是十分常见的 Java发展至今正常可能遇到的需求工具类,不要着急自己写一个,首先先找Java自带的util包下看看有没有,如果没有就到谷歌的common.lang3下的util包下,或者Spring社区当中也出了很多的工具包.只要是Spring相关的项目,引入简便,使用起来也十分轻松

48.如果需要精确的答案,请避免使用float和double

开发当中涉及到保留小数超过4位数建议使用Bigdecimal,如果只是普通的保留两位小数,double完全有这个实力能够计算准确,基本类型的double和Bigdecmail相比,性能大致相差5倍.如下代码所示

    public static void main(String[] args) {
        long begin = System.currentTimeMillis();
        BigDecimal sum = BigDecimal.ZERO;
        for(int i =0; i<=10000;i++){
            sum = sum.add(new BigDecimal(1));
        }
        long end = System.currentTimeMillis();
        System.out.println("BigDecimal总耗时:"+(end - begin)+"结果:"+sum);//5ms

        long begin1 = System.currentTimeMillis();
        double sum1 = 0;
        for(int i =0; i<=10000;i++){
            sum1 = sum1 + 1;
        }
        long end1 = System.currentTimeMillis();
        System.out.println("double总耗时:"+(end1 - begin1)+"结果:"+sum1);//0ms

    }

49.基本类型优先于装箱基本类型

  • 49.1 装箱基本类型属于引用类型,会在堆空间开辟一块新的内存空间,相比于基本类型,更加消耗性能,当计算次数越大,差别将会越明显
    public static void main(String[] args) {
        long begin = System.currentTimeMillis();
        Integer sum = 0;
        for(int i =0; i<=1000000;i++){
            sum = sum + 1;
        }
        long end = System.currentTimeMillis();
        System.out.println("Integer总耗时:"+(end - begin)+"ms,结果:"+sum);//10ms

        long begin1 = System.currentTimeMillis();
        int sum1 = 0;
        for(int i =0; i<=1000000;i++){
            sum1 = sum1 + 1;
        }
        long end1 = System.currentTimeMillis();
        System.out.println("int总耗时:"+(end1 - begin1)+"ms, 结果:"+sum1);//0ms
    }
  • 49.2 装箱基本类型和基本数据类型混合使用的时候,JVM编译器的自动拆装箱容易导致空指针异常,所以使用时记得类型的一致性保证
  • 49.3 装箱基本类型使用==比较的结果是比较两者在堆空间的地址值,这是不准确的

综上所述:能使用基本类型,就尽量别使用装箱基本类型

50.如果其他类型更适合,则尽量避免使用字符串

  • 50.1 字符串不适合代替其他的值类型.不要试图用String去替代int,double,boolean这些基本类型就能完成的事情
  • 50.2 字符串不适合代替枚举类型.枚举类型的一个大的特点就是简洁且安全,相比之下字符串都不具有这样的优势
  • 50.3 字符串不适合代替聚集类型.即是不要使用String的+号来拼接而形成一个新的字符串

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java基础-条件语句

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    cwl_java
  • 大数据-经典案例上行流量倒序排序(递减排序)

    分析,以需求一的输出数据作为排序的输入数据,自定义FlowBean,以FlowBean为map输 出的key,以手机号作为Map输出的value,因为MapRe...

    cwl_java
  • 数据结构与算法-打印梯形算法

    cwl_java
  • 写不好规范Java代码怎么去大厂

    解决办法 :引入Builder模式 场景:当构造器有5个或者以上的构造参数时或者目前参数不多但是以后会不断增多的时候。demo 如下:

    sowhat1412
  • 一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-使用UDA操纵SQL语句

           上一篇文章基于AgileEAS.NET平台基础类库进行应用开发-总体说明及数据定义中对本案例所涉及的数据表及部分数据,本文开始将从最基本的业务,数...

    魏琼东
  • java基础学习_常用类04_正则表达式、Math类、Random类、System类、BigInteger类、BigDecimal类、Date和DateFormat类、Calendar类_day14总

    ============================================================================= ==...

    黑泽君
  • 【编程题】Java编程题五(10道)

    【编程题】Java编程题六(10道) 【程序41】 题目:海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海...

    Java帮帮
  • 曾经做过的40道程序设计课后习题总结(四)

    曾经做过的40道程序设计课后习题总结(四) 课后习题目录 1 斐波那契数列 2 判断素数 3 水仙花数 4 分解质因数 5 杨辉三角 6 学习成绩查询...

    闵开慧
  • 史上Java最牛逼的代码

    确实是12306的最核心代码呀 <script> alert("当前访问用户过多,请稍后重试!"); </script> 确实牛 public clas...

    码神联盟
  • 分享史上Java最牛逼,最简短的代码

    确实是12306的最核心代码呀 <script> alert("当前访问用户过多,请稍后重试!"); </script> 确实牛 public clas...

    前朝楚水

扫码关注云+社区

领取腾讯云代金券