首先看一下三元运算符的格式
[条件语句] ? [表达式1] : [表达式2]
其中如条件语句为真执行表达式1,否则执行表达式2.简单的例子就不举了,来点其它的。在JDK1.5以前的版本中,表达式1和表达式2都要求是相同的类型,比如都是String或者char之类的,在JDK1.5以后,有了自动拆箱和装箱的原因,两者只要其中一种或者两者都能被拆箱即可,比如表达式1为Integer,而表达式2为int类型的,比如如下
1
int
a = 1;
2
Integer b = 2;
3
boolean
c = ture;
4
int
d = c ? b : a;
还有个需要注意的是,如果表达式1和表达式2的类型不相同,那么他们需要对交集类型的自动参考转换
。例如如下这段代码
1
String str = "abc";
2
StringBuilder strbu = new
StringBuilder("def");
3
boolean
boo = true
;
4
CharSequence cs = boo ? str : strbu;
因为String和StringBuilder都实现了CharSequence这个接口。
确定条件表达式结果类型的规则的核心是以下3点:
1 如果表达式1和表达式2操作数具有相同的类型,那么它就是条件表达式的类型。
2 如果一个表达式的类型是byte、short、char类型的,而另外一个是int类型的常量表达式,且它的值可以用类型byte、short、char三者之一表示的,那么条件表达式的类型就是三者之一
3 否则,将对操作数类型进行二进制数字提升,而条件表达式的类型就是第二个和第三个操作数被提升之后的类型
以上的三点可以用如下的代码来帮助理解:
1
char
ch = 'a';
2
int
num = 0 ;
3
boolean
bool = true
;
4
System.out.print( bool ? ch : 0); //这里不是 bool ? ch : num ,那样会打印两个97
5
System.out.print( !bool ? num : ch);
这段代码打印的是 a97 。很显然,第二点的规则应用到第一个打印上了,返回的是char,第三点的规则应用到第二个打印上了,返回的是int 。但是谁会在乎这个顺序导致的打印结果,所以为了避免不必要的麻烦,很显然显式强制类型转换
是个很不错的选择 -_-
1
char
ch = 'a';
2
int
num = 0 ;
3
boolean
bool = true
;
4
System.out.print( bool ? (char
)ch : (char
)0);
5
System.out.print( !bool ? (int
)num : (int
)ch);
还有值得注意的是 表达式1 和 表达式2 不一定非得是数据类型,还可以是自己定义的方法,只要方法有返回值
就行。例如
1
static
int
test1(int
i) {
2
i += 1;
3
return
i;
4
5
}
6
7
static
int
test2(int
i) {
8
i += 2;
9
return
i;
10
}
11
12
public
static
void
ternary() {
13
boolean
boo = false
;
14
int
c = boo ? test1(1) : test2(2);
15
}
以上就是个人的一点小心得~~有些内容可以参考[条件表达式规范[JLS 15.25]
什么是java三元运算符呢?无疑其操作元有三个,第一个是条件表达式,剩余两个为值,条件表达式为真时运算取第一个值,为假时取第二个值。
其示例代码如下:boolean a = 20 < 45 ? true : false;三元运算符的优先级高于赋值运算符,故判断表达式值为真,去第一个true,a的值为true。
三元运算符用于判断,其等价的if-else语句如下所示:
01 boolean a; //声明boolean变量
02 if(20<45) //将20<45作为判断条件
03 a = true; //条件成立将true赋值给a
04 else
05 a = false;
很多时候三元运算符可以和if-else语句进行互换,它们两个可以等价的实现判断的效果。但是三元运算符与if-else语句也还是有不同之处的,下面来具体的谈谈不同之处。
第一,两者之间对于返回值有不同的要求,三元运算符是必须要有返回值要求,其运算后一定会有一个结果返回供程序开发人员使用;而if-else语句并不一定有返回值,其执行结果可能是赋值语句或者打印输出语句(相信这一点大家都比较好理解)。
第二,两者的性能不同,三元运算符的运算性能相对于if-else语句来说要高一些,但是在一些小型的applet开发和日常学习开发中可以忽略不计。
第三,两者使用范围不同,在ireport的一些动态执行的情况下,只能用三元运算符而不能用if-else语句,当然在大多数情况下两者是可以等价互换的。
第四,两者的语言特性不同,三元运算符涉及到一种成为双目数值提升(binary numeric promotion)的语言特性。所谓的双目数值提升,在三目运算符java开发的环境下可以简单的理解为双目运算符的类型转换问题(便于理解)。其具体规则总结如下:
1)如果定义了数据类型的变量与未定义变量的数值共同参与三元运算符的后双目运算,,那么返回的结果就是范围大(精度高)类型
2)如果两个定义了数据类型的变量共同参与三元运算符的后双目运算,那么返回的结果就是范围大(精度高)类型
3)如果直接进行数值的比较,会自动转型成为范围大(精度高)的数据类型
而jvm在给数值分配数据类型的时候会选取刚好能装下该数据大小精度的数据类型进行分配(99.0为float,99为byte/short),在java中常见数据类型其范围从小到大(精度由高到低):byte<short<char<int<float<double。下面用一段代码来解释上述的三条规则,以下测试代码也涵盖了很多面试题目,希望各位可以从中理解上述三条规则。
01 char a='a';
02 int i=96;
03 //规则1,定义了数据类型的变量与未定义变量的数值,结果自动转换为精度高的
04 System.out.println(2==2?i:9.0);
05 //jvm给数值分配的数据类型,98并不是int类型的,而是byte/short,故结果会变为ASCII码98对应的字符
06 System.out.println(2==2?98:a);
07 //规则2,两个已经定义数据类型的变量,结果自动转换为精度高的
08 System.out.println(2==2?a:i);
09 //规则3,两个未定义的数值,结果自动转换为精度高的
10 System.out.println(2==2?99:9.0);
11 System.out.println(2==2?99:'b');
上述代码的执行结果为: 96.0
b
97
99.0
c
以前一直在C#中使用,得到的结果一直是如果两个数据类型不同,则会进行向上转型,如char-->int
Csharp代码
char x = 'X';
int i = 0;
System.Console.Write(true ? x : 0);
System.Console.Write(false ? i : x);
运行这段代码,会得到的结果是:8888.如上面的解释一样。(备注:如果x和i之间没有直接的类型转换,则无法编译通过)
但是,在java中执行,却是不同的结果。
Java代码
char x = 'X';
int i = 0;
System.out.println(true ? x : 0);
System.out.println(false ? i : x);
运行这段结果,得到的却是:X88,可以看到三元运算符的结果,与第二个表达式的类型有直接的关系。
对于第一个表达式:true ? x :0 因为x的类型为char,当表达式为真的时候,结果类型为char,得到的结果是X。
对于第二个表达式:false ? i : x,因为i的类型为整型,当表达式为false的时候,结果类型为int,于是char向上转型为整型,输出88。
结论:
1、在不同的开发语言中,一定要注意相同的语句,可能会存在不同的结果。
2、尽量避免在条件运算符两侧,使用不同的数据类型。
大家可以参阅上述代码与结果理解三元运算符的双目数值提升问题,由于本人水平有限,希望此文能给大家带来一定的帮助和启示,也希望各位不吝赐教,提出你们的宝贵建议。