Java条件运算符的类型
当初学Java时听说过三目运算符,偶尔用到,也没在意,直到后来看到某到题目(文中第五段代码)懵逼了,于是看了下题解,自己又码了些代码测试以为自己懂了,直到后来又遇到某情况(文中有,读者自己找)又懵逼了,才发现条件运算符不是那么单纯。
三目操作符的基本功能
条件运算符(?:)是Java中唯一的三目运算符。因此对于Java提到三目操作符,均指条件运算符。条件运算符可以用来进行代替 if else 语句来简化条件分支跳转。例如以下一段常见的代码:
boolean b = true;//boolean b = false;
int a;
if(b)
a = 1;
else
a = 2;
就可以用条件运算符简化为:
boolean b = true;//boolean b = false;
int a = b ? 1 : 2;
以上两段代码的意思都是:当布尔变量b是真时,a将赋值为1,b为false时,a将赋值为2。
所以条件运算符的一个基本用法是:
布尔变量a ? 表达式b : 表达式c; //(true)?1:2;
值得一提的是,b,c都不允许是void类型。
操作符两侧类型不同将会怎样
上面两段代码中,变量a和变量b都是int类型,所以没什么问题。那如果是不同类型会怎么样呢?
譬如这样:
boolean b = true;//boolean b = false;
int a = b ? 1.0 : 2;
甚至这样
boolean b = true;//boolean b = false;
int a = b ? 1 : new Object();
可以直接告诉读者,以上两段代码直接报错,因为不满足赋值语句一个基本的规则,右边必须是左边可以接受的类型。int显然不可能接受double,或者Object。
使用条件运算符给重载函数传参,且操作符两侧类型不同
你可能觉得事情就到此为止了,那不妨看看这看这两段代码:
boolean b = true;//boolean b = false;
System.out.println(b ? 1.0 : 2);
甚至这样
boolean b = true;//boolean b = false;
System.out.println(b ? 1.0 : new String("hello"));
或许就觉得有些困惑了,因为,毕竟System.out.print()方法具有大量重载,可以接受Java中所有的类型(即原始类型和对象的唯一根父类Object)。所以到底会不会报错呢?如果不报错,那么想必会出现类型转换,到底最终的类型会怎么决定呢?
是时候来点规则约束了–条件表达式的类型是什么?
讲真,这个规则有点复杂,推荐读者去看Oracle的官方Java语言文档15.25节。下面做一个简化规则介绍:
规则如下:
对于表达式 a ? b : c ,其类型由如下规则决定
- 如果b和c类型相同,那么表达式类型就是该类型。
- 如果b,c都是原始类型(即基本类型)或者原始类型的装箱类型,那么表达式将是某种原始类型,该原始类型是b,c中精度更高者。
下面对以上规则分别进行说明:
(1)如果a和b类型相同,那么表达式类型就是该类型。
这是最常见的使用场景,也是最安全的使用场景。
例如
System.out.println(a==4 ? "true" : "false");
(2)如果b,c都是原始类型或者基本类型的装箱类型,那么表达式将是某种原始类型,该原始类型是b,c中精度更高者。
//左边为int,右边为double
System.out.println(true ? 97 : 97.0);
//输出结果是97.0
这个例子很典型,int和double都是原始类型。在Java中,原始类型的精度排序从低到高是int(32位)->double(64位),因此int将会向上扩展位数转换为double。
//左边为char,右边为double
System.out.println(true ? 'a' : 2.0);
//输出结果是97.0
char是16位,会转成64位的double。
//左边为Character,右边为double
System.out.println(true ? new Character('a') : 2.0);
//输出结果是97.0
Character的拆箱类型是char,之后同上面的例子。
看似上面的规则已经行之有效,但是你或许会碰到下面的例子。
规则二的补充——int的特殊性
//左边为char,右边为int
System.out.println(true ? 'a' : 97);
//输出结果是a
//左边为char,右边为int
System.out.println(true ? 'a' : 65535);
//输出结果是a
//左边为char,右边为int
System.out.println(true ? 'a' : 65536);
//输出结果是97
第一个和第二个按照规则而看似应该是char转成int,然而事实并没有这样。这是因为int的特殊性,在java中可以直接使用数字对char进行赋值,而char的位数有16位,因此范围是0~2^16-1,也就是0~65535。譬如
char x=97;
System.out.println(a);
//输出a
是合法的语句,且输出是a,即ASCII码表中97对应的字符。因此,前两句中右边的值的类型会被判定为char。因此左右两边都是char。而第三个例子中65536已经超过了char的范围,必然是一个int了。因此左边的’a’会向更高精度的int转换输出97.
因此需要补充一个规则。
如果b和c中,有一个是类型T(仅限于char,byte,short),有一个是用int表示的类型T,则表达式的类型是类型T。
正如上面所说,在Java中,char,byte,short可以通过int来赋值的,在条件表达式中,b,c如果是char,byte,short之一和int,那么这时候int极有可能不被认为是整数了,只要它满足对应类型的 取值范围。
兼容性
在Java 4之前,条件运算符的b,c表达式如果类型不同,会直接编译报错。
总结
Java的三目操作符有时固然好用,但是一旦涉及操作符两侧类型不同,事情就不是那么容易看穿的了,所以还是慎用吧。
练习
判断以下表达式的类型
true ? 97 : 97 ; //int
true ? 97 : 97.0 ; //double
true ? ‘a’ : 97 ; //char
true ? 97 : ‘a’ ; //char
true ? 65536 : ‘a’; //int
true ? ‘a’ : 65536 ; //int
true ? 97 : new Integer(97); //int
true ? 97.0 : new Integer(97); //double
true ? 97 : new Double(97); //double
共有 0 条评论