三目运算符使用的一些注意事项, 三目运算符中的一些“潜规则“

三目运算符格式:

expression1 ? expression2 : expression3

注意事项:

1. java虚拟机在编译三目运算时是以 “?” 和 “:” 来判断各位置的代码充当的结构。“?”前作为一部分,“?”和“:”中间作为一部分,“:”后作为一部分 。

表达式一:int temp = 0 < 1 ? c = c + 1 : d = d + 1;

错误,编译无法通过。Java虚拟机把上式看成了int temp = (0<1?c=c+1:d)=d+1,并没有把d=d+1当成一个整体。

应改为int temp = 0 < 1 ? c = c + 1 : (d = d + 1);

表达式二:int temp = 0 < 1 ? c = c + 1 : d++;

正确。Java对++运算符有特殊的运行规则,所以能够正常编译

2.三目运算符中的类型转换

例一:整型转换为浮点型

double a = 3 > 4 ? 4 : 2;
System.out.println(a);

输出结果:value is 2.0

例二:  三目运算的潜规则

有时候,我们为了代码的简洁性,会引入三目运算符:

double d1 = (null != dWarp1) ? dWarp1 : 0;

但是,也有比较诡异的情况:根据条件flag判断,如果true则赋值dWarp1,否则设为默认值0,如下。

Double dWarp1 = null;
boolean flag =true;
Double dWarp2 = (flag) ? dWarp1 : 0.0;

 这乍眼一看,很正常嘛,相当于dWarp2 = dWarp1,但是运行起来却会抛异常NullPointerException

 这就是编译器的自动装箱/拆箱转换引起的问题。我们反编译就能看到,原来他对dWarp1做了一层拆箱,这样就出现前面我们所说的问题,如果dWarp1为null的话,就挂了。

Double dWarp2 = Double.valueOf((flag) ? dWarp1.doubleValue() : 0.0);

 其实,这是自动装箱/拆箱的特性,只要一个运算中有不同的类型,涉及到类型转换,那么编译器会往下(基本类型)转型,再进行运算。 就是说,如果运算中有int和Integer,Integer会先转成int再计算。

 所以下面这种写法照样会抛出NullPointerException:

Double dWarp1 = null;
Long l2 = null;
boolean flag =false;
Double dWarp2 = (flag) ? dWarp1 : l2;

因为dWarp1和l2都要先转换成基本类型,而不是互相转换,反编译后变成:

    Double dWarp2 = Double.valueOf((flag)? dWarp1.doubleValue() : l2.longValue());

 因此,这里可以改成下面三种方式: 

1. 在赋值前,先做非空校验,但是这样做比较繁琐,因为很多时候dWarp2是可以接受null的,这个非空判断只是用来避免编译器的自动拆箱异常。

2. 避免使用三目运算符,不过估计会有很多人不忍抛弃三目(我也算一个)。

        Double dWarp1 = null;
        boolean flag =true;
        Double dWarp2 = 0;
        if (flag) {
            dWarp2 = dWarp1;
        }

3. 统一运算中的类型,避免类型的混用了。(个人觉得这种比较优雅)

        Double dWarp1 = null;
        boolean flag =true;
        DoubledWarp2 = (flag) ? dWarp1 : Double.valueOf(0);

你可能感兴趣的:(错误示例,Java干货,思考题目,java,javase)