前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3分钟快速阅读-《Effective Java》(五)

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

作者头像
cwl_java
发布2019-10-26 20:48:03
4170
发布2019-10-26 20:48:03
举报
文章被收录于专栏:cwl_Javacwl_Java
41.慎用重载

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

代码语言:javascript
复制
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.慎用可变参数

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

  • 错误做法
代码语言:javascript
复制
    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;
    }
  • 正确做法
代码语言:javascript
复制
    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,那么就会需要调用方来处理这个问题,此时我们应该尽可能的自己来解决这个异常,以避免给调用者带来不必要的麻烦

  • 错误做法
代码语言:javascript
复制
    private final List<Cheese> cheeses = new ArrayList<>(10);
    public List<Cheese> getCheeses(){
        if(cheeses.size() == 0){
            return null;
        }
        return cheeses;
    }
  • 正确做法
代码语言:javascript
复制
    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倍.如下代码所示

代码语言:javascript
复制
    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 装箱基本类型属于引用类型,会在堆空间开辟一块新的内存空间,相比于基本类型,更加消耗性能,当计算次数越大,差别将会越明显
代码语言:javascript
复制
    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的+号来拼接而形成一个新的字符串
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 41.慎用重载
  • 42.慎用可变参数
  • 43.返回0长度的数组或者集合,而不是null
  • 44.为所有导出的API元素编写文档注释
  • 45.将局部变量的作用域最小化
  • 46.foreach循环优先于传统的for循环
  • 47.了解和使用类库
  • 48.如果需要精确的答案,请避免使用float和double
  • 49.基本类型优先于装箱基本类型
  • 50.如果其他类型更适合,则尽量避免使用字符串
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档