2.15 表达式
运算符、变量和字面量都是表达式(expression)的组成部分。当在程序中遇到表达式时,会计算该表达式。因为它在前面的程序中已经用过,所以读者可能对表达式已有相当的直观理解。另外,Java的表达式也与代数中的表达式类似。但是,现在还是要讨论表达式的一些方面。
2.15.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型。这与直观感觉不同。考虑以下程序:
与直观感受相反,当把bb赋给变量i时,不需要强制类型转换,因为在计算表达式时,变量b已经提升为int类型。但是,如果将bb赋给b,需要使用强制类型转换将类型变回byte类型。记住,如果获得了与期望不同的类型,在表达式上会有提示不兼容的错误消息。否则,一切就都好。
同样的情况在执行与char类型有关的操作时也会发生。例如,在下面的代码片段中,由于表达式将变量ch1和ch2提升为int类型,需要使用强制类型转换转回char类型。
如果没有强制类型转换,将ch1加到ch2的结果就是int类型,不能赋给变量ch1。
强制类型转换不仅在赋值中的类型转换有用。例如,考虑下面的示例。它使用强制类型转换将数据转化为double类型来获得结果的小数部分。若不使用强制类型转换,则涉及的除法仅是整数除法。
程序输出如下所示:
2.15.2 空白和圆括号
在Java的表达式中,可以使用水平制表符和空格增加可读性。例如,下面两个表达式完全相同,但后者更易阅读:
圆括号从代数角度改变了其中运算的优先级。使用额外的圆括号不会导致错误,也不会降低表达式的执行速度。鼓励大家使用圆括号来使运行顺序更明确,便于后来人阅读程序。例如,请判断以下两个表达式中哪个更容易阅读: