我是靠谱客的博主 纯真白羊,这篇文章主要介绍java核心技术卷1---运算符,现在分享给大家,希望可以做个参考。

在 Java 中,使用算术运算符+、-、*、/ 表示加、减、乘、除运算。当参与 / 运算的两个操作数都是整数时,表示整数除法;否则,表示浮点除法。整数的求余操作(有时称为取模)用 % 表示。例如,15/2 等于 7,15%2 等于 1,15.0/2 等于 7.5。

需要注意,整数被 0 除将会产生一个异常,而浮点数被 0 除将会得到无穷大或 NaN 结果。可以在赋值语句中采用一种简化的格式书写二元算术运算符。
例如,

等价于
(通常,将运算符放在赋值号的左侧,如
*= 或 %=。)

注释:可移植性是 Java 语言的设计目标之一。无论在哪个虚拟机上运行,同一运算应该得到同样的结果。对于浮点数的算术运算,实现这样的可移植性是相当困难的。double类型使用 64 位存储一个 double 数值,而有些处理器使用 80 位浮点寄存器。这些寄存器增加了中间过程的计算精度。例如,下列运算:

很多 Intel 处理器计算 x * y,并且将结果存储在 80 位的寄存器中,再除以 z 并将结果截断为 64 位。这样可以得到一个更加精确的计算结果,并且还能够避免产生指数溢出。但是,这个结果可能与始终在 64 位机器上计算的结果不一样。因此,Java 虚拟机的最初规范规定所有的中间计算都必须进行截断。这种行为遭到了数值计算团体的反对。截断计算不仅可能导致溢出,而且由于截断操作需要消耗时间,所以在计算速度上要比精确计算慢。为此,Java 程序设计语言承认了最优性能与理想结果之间存在的冲突,并给予了改进。在默认情况下,虚拟机设计者允许将中间计算结果采用扩展的精度。但是,

40 第 3 章 Java 的基本程序设计结构
对于使用 strictfp 关键字标记的方法必须使用严格的浮点计算来产生理想的结果。例如,

可以把 main 方法标记为

于是,在 main 方法中的所有指令都将使用严格的浮点计算。如果将一个类标记为strictfp,这个类中的所有方法都要使用严格的浮点计算。

实际的计算方式将取决于 Intel 处理器。在默认情况下,中间结果允许使用扩展的指数,但不允许使用扩展的尾数(Intel 芯片在截断尾数时并不损失性能)。因此,这两种方式的区别仅仅在于采用默认的方式不会产生溢出,而采用严格的计算有可能产生溢出。

如果没有仔细阅读这个注释,也没有什么关系。对大多数程序来说,浮点溢出不属于大问题。在本书中,将不使用 strictfp 关键字。

3.5.1 自增运算符与自减运算符

当然,程序员都知道加 1、减 1 是数值变量最常见的操作。在 Java 中,借鉴了 C 和 C++的实现方式,也使用了自增、自减运算符:n++ 将变量 n 的当前值加 1 ;n–– 将 n 的值减 1。例如:

n 的值将变为 13。因为这些运算符改变了变量的值,所以它的操作数不能是数值。例如,4++ 就是一条非法的语句。

实际上,这两个运算符有两种形式。上面介绍的是运算符放在操作数后面的“后缀”形式,还有一种“前缀”形式,++n。两种方式都是对变量值加 1。但在表达式中,这两种形式就有区别了。前缀方式先进行加 1 运算;后缀方式则使用变量原来的值。

我们建议不要在其他表达式的内部使用 ++,这样编写的代码很容易令人困惑,并会产生烦人的 bug。

(当然,++ 运算符作为 C++ 语言名称的一部分,也引发了有关程序设计语言的第一个笑话。C++ 的反对者认为这种语言的名称也存在着 bug,他们说:“因为只有对它改进之后,我们才有可能使用它,所以它的名字应该命名为 ++C。”)

3.5.2 关系运算符与 boolean 运算符

Java 包含各种关系运算符。其中,使用两个等号 = = 检测是否相等。例如,3 = = 7 的值为 false。

使用 != 检测是否不相等。例如,3 != 7 的值为 true。
另外,经常使用的运算符还有
<(小于)、>(大于)、<=(小于等于)和 >=(大于等于)。

3.5 运算符 41

Java 沿用了 C++ 的习惯,用 && 表示逻辑“与”、用 || 表示逻辑“或”。从 != 运算符很容易看出,! 表示逻辑“非”。&& 和 || 是按照“短路”方式求值的。如果第一个操作数已经能够确定表达式的值,第二个操作数就不必计算了。如果用 && 对两个表达式进行计算:

并且第一个表达式值为 false,结果不可能为真。因此,第二个表达式的值就没有必要计算了。这种方式可以避免一些错误的发生。例如,表达式:

当 x 为 0 时,不会计算第二部分。因此,若 x 为 0,1/x 不被计算,也不会出现除以 0 的错误。与之类似,对于 expression1 || expression2,当第一个表达式为 true 时,结果自动为 true,

不必再计算第二部分。
最后,
Java 支持三元操作符 ?:。在很多时候,这个操作符非常有用。表达式

当条件 condition 为真时计算第 1 个表达式,否则计算第 2 个表达式。例如:

返回 x 和 y 中较小的那个值。3.5.3 位运算符

在处理整型数值时,可以直接对组成整型数值的各个位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位。位运算符包括:

&(" 与 ")、|(" 或 ")、^(" 异或 ")、~(" 非 ")

这些运算符在位模式下工作。例如,如果 n 是一个整型变量,并且用二进制表示的 n 从右数第 4 位为 1,那么

返回 1 ;否则返回 0。通过运用 2 的幂次方的 & 运算可以将其他位屏蔽掉,而只保留其中的某一位。

注释:& 和 | 运算符应用于布尔值,得到的结果也是布尔值。这两个运算符与 && 和 ||的运算非常类似,只是不按“短路”方式计算。即在得到计算结果之前,一定要计算两个操作数的值。

另外,“ >>”和“ <<”运算符将二进制位进行右移或左移操作。当需要建立位模式屏蔽某些位时,使用这两个运算符十分方便:

最后,>>> 运算符将用 0 填充高位;>> 运算符用符号位填充高位。没有 <<< 运算符。

警告:对移位运算符右侧的参数需要进行模 32 的运算(除非左边的操作数是 long 类型,在这种情况下需对右侧操作数模 64)。例如,1 << 35 与 1 << 3 或 8 是相同的。

42 第 3 章 Java 的基本程序设计结构

C++ 注释:在 C 或 C++ 中无法确定 >> 操作执行的是算术移位(扩展符号位),还是逻辑移位(高位填 0)。在执行中将会选择效率较高的一种。这就是说,在 C/C++ 中,>> 运算符实际上只是为非负数定义的。Java 消除了这种含糊性。

3.5.4 数学函数与常量

在 Math 类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。

要想计算一个数值的平方根,可以使用 sqrt 方法:

注释:println 方法和 sqrt 方法存在微小的差异。println 方法操作一个定义在 System 类中的 System.out 对象。但是,Math 类中的 sqrt 方法处理的不是对象,这样的方法被称为静态方法。有关静态方法的详细内容请参看第 4 章。

在 Java 中,没有幂运算,因此需要借助于 Math 类的 pow 方法。语句:

将 y 的值设置为 x 的 a 次幂(xa)。pow 方法有两个 double 类型的参数,其返回结果也为double 类型。

Math 类提供了一些常用的三角函数:

还有指数函数以及它的反函数— 自然对数以及以 10 为底的对数:最后,Java 还提供了两个用于表示 p 和 e 常量的近似值:

提示:不必在数学方法名和常量名前添加前缀“ Math.”,只要在源文件的顶部加上下面这行代码就可以了。

例如:
在第
4 章中将讨论静态导入。

注释:在 Math 类中,为了达到最快的性能,所有的方法都使用计算机浮点单元中的例程。如果得到一个完全可预测的结果比运行速度更重要的话,那么就应该使用 StrictMath类。它使用“自由发布的 Math 库”(fdlibm)实现算法,以确保在所有平台上得到相同的结果。有关这些算法的源代码请参看 www.netlib.org/fdlibm(当 fdlibm 为一个函数提供了多个定义时,StrictMath 类就会遵循 IEEE 754 版本,它的名字将以“e”开头)。

3.5.5 数值类型之间的转换在程序运行时,经常需要将一种数值类型转换为另一种数值类型。图 3-1 给出了数值类

型之间的合法转换。

3.5 运算符 43

图 3-1 数值类型之间的合法转换

在图 3-1 中有 6 个实心箭头,表示无信息丢失的转换;有 3 个虚箭头,表示可能有精度损失的转换。例如,123 456 789 是一个大整数,它所包含的位数比 float 类型所能够表达的位数多。当将这个整型数值转换为 float 类型时,将会得到同样大小的结果,但却失去了一定的精度。

当使用上面两个数值进行二元操作时(例如 n + f,n 是整数,f 是浮点数),先要将两个操作数转换为同一种类型,然后再进行计算。

● 如果两个操作数中有一个是 double 类型,另一个操作数就会转换为 double 类型。● 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
● 否则,如果其中一个操作数是 long 类型,另一个操作数将会转换为 long 类型。
● 否则,两个操作数都将被转换为 int 类型。

3.5.6 强制类型转换

在上一小节中看到,在必要的时候,int 类型的值将会自动地转换为 double 类型。但另一方面,有时也需要将 double 转换成 int。在 Java 中,允许进行这种数值之间的类型转换。

44 第 3 章 Java 的基本程序设计结构

当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换(cast)实现这个操作。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。例如:

这样,变量 nx 的值为 9。强制类型转换通过截断小数部分将浮点值转换为整型。如果想对浮点数进行舍入运算,以便得到最接近的整数(在很多情况下,希望使用这种

操作方式),那就需要使用 Math.round 方法:

现在,变量 nx 的值为 10。当调用 round 的时候,仍然需要使用强制类型转换(int)。其原因是 round 方法返回的结果为 long 类型,由于存在信息丢失的可能性,所以只有使用显式的强制类型转换才能够将 long 类型转换成 int 类型。

警告:如果试图将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值。例如,(byte)300 的实际值为 44。

C++ 注释:不要在 boolean 类型与任何数值类型之间进行强制类型转换,这样可以防止发生错误。只有极少数的情况才需要将布尔类型转换为数值类型,这时可以使用条件表达式 b ? 1:0。

3.5.7 括号与运算符级别

表 3-4 给出了运算符的优先级。如果不使用圆括号,就按照给出的运算符优先级次序进行计算。同一个级别的运算符按照从左到右的次序进行计算(除了表中给出的右结合运算符外。)例如,由于 && 的优先级比 || 的优先级高,所以表达式

等价于

又因为 += 是右结合运算符,所以表达式

等价于

也就是将 b += c 的结果(加上 c 之后的 b)加到 a 上。

C++ 注释:与 C 或 C++ 不同,Java 不使用逗号运算符。不过,可以在 for 语句中使用逗号分隔表达式列表。

表 3-4运算符

运算符优先级

[ ] . ( ) ( 方法调用 )
! ~ ++ -- + (
一元运算 ) - ( 一元运算 ) ( ) ( 强制类型转换 ) new 从右向左

*/ % 从左向右

+– 从左向右

<< >> >>> 从左向右

< <= > >= instanceof 从左向右

== != 从左向右

& 从左向右

^ 从左向右

| 从左向右

&& 从左向右

|| 从左向右

?: 从右向左

= += – = *= /= %= &= |= ^= <<= >>= >>>= 从右向左 

最后

以上就是纯真白羊最近收集整理的关于java核心技术卷1---运算符的全部内容,更多相关java核心技术卷1---运算符内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(336)

评论列表共有 0 条评论

立即
投稿
返回
顶部