表达式由运算符,变量和字面值组成.从其他编程经验或代数中,你可能已经知道了表达式的基本形式.然而,这里还需要对表达式的几个方面进行介绍.
1.表达式中的类型转换
只要类型兼容,在表达式总就可以混合使用一种或多种不同类型的数据.例如,可以在表达式中混合使用short和long,因为他们都是数值类型.当在表达式中混合使用不同类型的数据时,他们都被转换为同一类型.这是通过使用Java的类型升级规则(type promotion rule)完成的.
首先,所有的char,byte和short值都被升级为int.其次,如果有一个操作数是long类型,整个表达式就全部升级为long类型.如果有一个操作数是float类型,整个表达式就全部升级为float类型.如果有一个操作数是double类型,整个表达式就全部升级为double类型.
当计算表达式时,类型升级只应用于被操作的值,理解这一点是非常重要的.例如,如果在一个表达式中,一个byte类型变量的值升级为int.那么在表达式以外,该变量仍然是byte类型.类型升级只影响表达式的计算.
然而类型升级可能导致某些不可预测的错误.例如,当一个算术运算包括两个byte值时,就会顺序发生以下事情:首先,byte类型的操作数升级为int;然后,进行运算,生成一个int类型的结果.因此,包括两个byte类型的运算结果将会成为一个int类型的值.而这可能不是一下就能预见到的.
public static void main(String args[]) { byte b; int i; b = 10; i = b * b; b = 10; b = (byte)(b * b); }
有些出乎意料的是,因为当计算表达式时b被升级为int,所以把b*b赋值给i时不需要强制转换.然而当试图将b*b赋值给b时,却需要强制转换回byte类型!如果看上去表达式完全没有问题,但是却出现意外的类型不兼容错误,那就应该想到这一点.
在执行有关char的运算时也会有同样的情况发生.例如,在下面的代码段中,因为表达式中ch1和ch2升级为int,所以需要将其强制转换为char;
char ch1,ch2; ch1 = 'a'; ch2 = 'b'; ch1 = (char)(ch1 + ch2);
如果没有强制转换,ch1+ch2的结果为int类型,这是无法赋值给一个char类型的变量的.
强制转换不只在赋值的时候有用,考虑下面的程序,从整除强制转换为double来获得小数部分.
public static void main(String args[]) { int i; for(i = 0;i<5;i++) { System.out.println(i+" / 3 :"+i/3); System.out.println(i+" / 3 with fractins : "+(double)i/3); } }
输出:
0 / 3 :0 0 / 3 with fractins : 0.0 1 / 3 :0 1 / 3 with fractins : 0.3333333333333333 2 / 3 :0 2 / 3 with fractins : 0.6666666666666666 3 / 3 :1 3 / 3 with fractins : 1.0 4 / 3 :1 4 / 3 with fractins : 1.3333333333333333
2.间距和圆括号
Java中的表达式可以使用制表符和空格来增强可读性,例如,下面的两个表达式作用相同,但是第二个表达式更易读:
x=10/y*(127/x) x=10 / y * ( 127 / x )
与代数中圆括号的作用一样,增加了所包括的运算的优先级.使用多余或附加的圆括号不会引发错误,也不会减慢表达式的执行.Java提倡使用圆括号以使计算的顺序清晰,帮助你自己以及其他阅读程序的人更好的理解程序.