今天遇到了一个三目运算符使用上的问题,看了半天也没发现有啥不对的。
打断点简化过后的程序是这样的:
public static void main(String[] args) {
Integer a = 2;
Integer b = 2;
Integer c = null;
Integer result = false ? a+b : c;
}
但是把 c 改成 null 就没问题
Integer result = false ? a+b : null;
这样却能正常执行。
最后在 阿里技术 这个公众号上看到了 三目运算符的类型转化规则:
1、若两个表达式类型相同,返回值类型为该类型;
2、若两个表达式类型不同,但类型不可转换,返回值类型为 Object 类型;
3、若两个表达式类型不同,但类型可以转化,先把包装数据类型转化为基本数据类型,然后按照基本数据类型的转换规则 (byte < short(char)< int < long < float < double) 来转化,返回值类型为优先级最高的基本数据类型。
看到这里大概就知道问题在哪里了。
Integer result = false ? a+b : c;
a+b 结果为基本数据类型,c 是包装数据类型,根据第3条规则 c 会转换为基本数据类型,所以报空指针异常。
Integer result = false ? a+b : null;
这个表达式不报错是因为 null 不属于任何类型,所以 null 不会进行类型转换所以没问题。
public static void main(String[] args) {
Integer a = 2;
Integer b = 2;
Integer result = false ? a+b : null;
}
对应字节码:
public class test.Test {
public test.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_2
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: iconst_2
6: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: astore_2
10: aconst_null
11: astore_3
12: return
}
null是个特殊的存在。
我们接下来试用第二条规则:
若两个表达式类型不同,但类型不可转换,返回值类型为 Object 类型;
Integer a = 2;
Integer b = 2;
String c = null;
Object result = false ? a+b : c;
如果不用 Object 类型,编译期间就提示错误了。
第一条规则:
若两个表达式类型相同,返回值类型为该类型
public static void main(String[] args) {
Integer a = 2;
Integer c = null;
Integer result = false ? a : c;
}
都是包装数据类型不进行数据转换,运行正常。
最后:
因为发现了问题所在,最后我使用了 if ... else ...,哈哈!
public static void main(String[] args) {
Integer a = 2;
Integer b = 2;
Integer c = null;
Integer result = null;
if(a > b) {
result = a + b;
}else {
result = c;
}
}
这样就绝对稳了。