美文网首页三月听我说
编写高质量的JAVA代码

编写高质量的JAVA代码

作者: 东北小贰爷 | 来源:发表于2018-09-02 11:23 被阅读32次

    前言

    这是一个英雄辈出的年代,我们每一个人都希望自己被顶礼膜拜,这可是需要资本和实力,而我们的实力提现了我们处理技术问题的能力:

    • 你能写出简单、清晰、 高效的代码么?——Show it !
    • 你能架构一个稳定、健壮、快捷的系统?——Do it!
    • 你能回答一个困扰N多人的问题?——Answer it!
    • 你能修复一个系统Bug?——Fix it!
    • 你非常熟悉某个开源产品?——Broadcast it!
    • 你能提升系统性能?——Tune it!
    • ……

    ===================说正事专用线===================

    三元操作符的类型务必一致

    三元操作符是if-else的简化写法,在项目中使用它的地方很多,也非常好用,但是好用又简单的东西并不表示就可以随便用,我们来看看下面这段代码:

    public class Client {
        public static void main(String[] args) {
                int i = 80;
                String s = String.valueOf(i<100?90:100);
                String s1 = String.valueOf(i<100?90:100.0);
                System.out.println("两者是否相等:"+s.equals(s1));
        }
    }
    

    分析一下这段程序:i是80,那它当然小于100,两者的返回值肯定都是90,再转成String类型,其值也绝对相等,毋庸置疑的。恩,分析得有点道理,但是变量s中三元操作符的第二个操作数是100,而s1的第二个操作数是100.0,难道没有影响吗?不可能有影响吧,三元操作符的条件都为真了,只返回第一个值嘛,与第二个值有一毛钱的关系吗?貌似有道理。
    果真如此吗?我们通过结果来验证一下,运行结果是:“两者是否相等:false”,什么?不相等,Why?
    问题就出在了100和100.0这两个数字上,在变量s中,三元操作符中的第一个操作数(90)和第二个操作数(100)都是int类型,类型相同,返回的结果也就是int类型的90,而变量s1的情况就有点不同了,第一个操作数是90(int类型),第二个操作数却是100.0,而这是个浮点数,也就是说两个操作数的类型不一致,可三元操作符必须要返回一个数据,而且类型要确定,不可能条件为真时返回int类型,条件为假时返回float类型,编译器是不允许如此的,所以它就会进行类型转换了,int型转换为浮点数90.0,也就是说三元操作符的返回值是浮点数90.0,那这当然与整型的90不相等了。这里可能有读者疑惑了:为什么是整型转为浮点,而不是浮点转为整型呢?这就涉及三元操作符类型的转换规则:

    • 若两个操作数不可转换,则不做转换,返回值为Object类型。
    • 若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。
    • 若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
    • 若两个操作数都是直接量数字,则返回值类型为范围较大者。
      知道是什么原因了,相应的解决办法也就有了:保证三元操作符中的两个操作数类型一致,即可减少可能错误的发生。

    警惕自增的陷阱

    记得大学刚开始学C语言时,老师就说:自增有两种形式,分别是i++和++i,i++表示的是先赋值后加1,++i是先加1后赋值,这样理解了很多年也没出现问题,直到遇到如下代码,我才怀疑我的理解是不是错了:

    public class Client {
          public static void main(String[] args) {
                  int count =0;
                  for(int i=0;i<10;i++){
                          count=count++;
                  }
                  System.out.println("count="+count);
        }
    }
    

    这个程序输出的count等于几?是count自加10次吗?答案等于10?可以非常肯定地告诉你,答案错误!运行结果是count等于0。为什么呢?
    count++是一个表达式,是有返回值的,它的返回值就是count自加前的值,Java对自加是这样处理的:首先把count的值(注意是值,不是引用)拷贝到一个临时变量区,然后对count变量加1,最后返回临时变量区的值。程序第一次循环时的详细处理步骤如下:
    步骤1 JVM把count值(其值是0)拷贝到临时变量区。
    步骤2 count值加1,这时候count的值是1。
    步骤3 返回临时变量区的值,注意这个值是0,没修改过。
    步骤4 返回值赋值给count,此时count值被重置成0。
    “count=count++”这条语句可以按照如下代码来理解:

    public static int mockAdd(int count){
        //先保存初始值
        int temp =count;
        //做自增操作
        count = count+1;
        //返回原始值
        return temp;
    }
    

    于是第一次循环后count的值还是0,其他9次的循环也是一样的,最终你会发现count的值始终没有改变,仍然保持着最初的状态。
    此例中代码作者的本意是希望count自增,所以想当然地认为赋值给自身就成了,不曾想掉到Java自增的陷阱中了。解决方法很简单,只要把“count=count++”修改为“count++”即可。该问题在不同的语言环境有不同的实现:C++中“count=count++”与“count++”是等效的,而在PHP中则保持着与Java相同的处理方式。每种语言对自增的实现方式各不同,读者有兴趣可以多找几种语言测试一下,思考一下原理。
    下次如果看到某人T恤上印着“i=i++”,千万不要鄙视他,记住,能够以不同的语言解释清楚这句话的人绝对不简单,应该表现出“如滔滔江水”般的敬仰,心理默念着“高人,绝世高人哪”。

    用偶判断,不用奇判断

    判断一个数是奇数还是偶数是小学里学的基本知识,能够被2整除的整数是偶数,不能被2整除的是奇数,这规则简单又明了,还有什么好考虑的?好,我们来看一个例子,代码如下:

    public class Client {
        public static void main(String[] args) {
                //接收键盘输入参数
                Scanner input = new Scanner(System.in);
                System.out.print("请输入多个数字判断奇偶:");
                while(input.hasNextInt()){
                        int i = input.nextInt();
                        String str =i+ "->" + (i%2 ==1?"奇数":"偶数");
                        System.out.println(str);
                }
        }
    }
    

    输入多个数字,然后判断每个数字的奇偶性,不能被2整除就是奇数,其他的都是偶数,完全是根据奇偶数的定义编写的程序,我们来看看打印的结果:

    请输入多个数字判断奇偶:120 -1 -2
    1->奇数
    2->偶数
    0->偶数
    -1->偶数-2->偶数
    前三个还很靠谱,第四个参数-1怎么可能会是偶数呢,这Java也太差劲了,如此简单的计算也会错!别忙着下结论,我们先来了解一下Java中的取余(%标示符)算法,模拟代码如下:

    //模拟取余计算,dividend被除数,divisor除数
    public static int remainder(int dividend,int divisor){
        return dividend - dividend / divisor * divisor;
    }
    

    看到这段程序,相信大家都会心地笑了,原来Java是这么处理取余计算的呀。根据上面的模拟取余可知,当输入-1的时候,运算结果是-1,当然不等于1了,所以它就被判定为偶数了,也就是说是我们的判断失误了。问题明白了,修正也很简单,改为判断是否是偶数即可,代码如下:

    i%2 ==0?"偶数":"奇数"
    注意 对于基础知识,我们应该“知其然,并知其所以然”。

    相关文章

      网友评论

        本文标题:编写高质量的JAVA代码

        本文链接:https://www.haomeiwen.com/subject/totmwftx.html