Operators

Operators

运算符

The usual arithmetic operators +* / are used in Java for addition, subtraction, multiplication, and division. The / operator denotes integer division if both arguments are integers, and floating-point division otherwise. Integer remainder (sometimes called modulus) is denoted by %. For example, 15 / 2 is 7, 15 % 2 is 1, and 15.0 / 2 is 7.5.

通常的运算符 +* / Java中也被用作加、减、乘、除。如果除数和被除数都是整数,则运算符 /表示整除法(商为整数),否则为浮点除法。整除取余(有的时候叫“模”)用 %来表示。例如,15 / 2等于715 % 2等于1,而15.0 / 2等于7.5

Note that integer division by 0 raises an exception, whereas floating-point division by 0 yields an infinite or NaN result.

注意整数被0除会引发异常,然而浮点数被0除则得到无穷(infinite)或无意义(NaN)的结果。

There is a convenient shortcut for using binary arithmetic operators in an assignment. For example,

在赋值时使用二元运算符有一个快捷的办法。例如:

 

x += 4;

 

is equivalent to

等价于

 

x = x + 4;

 

(In general, place the operator to the left of the = sign, such as *= or %=.)

(大体上是,将运算符放在符号 = 的左侧,就好像 *= 或是 %=。)

NOTE

注释

One of the stated goals of the Java programming language is portability. A computation should yield the same results no matter which virtual machine executes it. For arithmetic computations with floating-point numbers, it is surprisingly difficult to achieve this portability. The double type uses 64 bits to store a numeric value, but some processors use 80-bit floating-point registers. These registers yield added precision in intermediate steps of a computation. For example, consider the computation:

Java编程语言的一个明确的目标就是可移植性。一个计算,无论那个虚拟机运行他都应该得到相同的结果。浮点数的数值运算在实现可移植性方面是令人难以置信的困难。double类型使用64个字位存储数值,但有些处理器使用80位浮点寄存器。这些寄存器会在计算中间步骤产生额外的精度。例如,设想计算:

 

double w = x * y / z;

 

Many Intel processors compute x * y and leave the result in an 80-bit register, then divide by z and finally truncate the result back to 64 bits. That can yield a more accurate result, and it can avoid exponent overflow. But the result may be different from a computation that uses 64 bits throughout. For that reason, the initial specification of the Java virtual machine mandated that all intermediate computations must be truncated. The numeric community hated it. Not only can the truncated computations cause overflow, they are actually slower than the more precise computations because the truncation operations take time. For that reason, the Java programming language was updated to recognize the conflicting demands for optimum performance and perfect reproducibility. By default, virtual machine designers are now permitted to use extended precision for intermediate computations. However, methods tagged with the strictfp keyword must use strict floating-point operations that yield reproducible results. For example, you can tag main as

多数Intel处理器计算x * y并将结果放在80位寄存器中,再除以z,并将结果最终截短还原为64位。那样可以得到一个更精确的结果,而且可以避免指数溢出。但是这个结果就有可能不同于始终用64位进行的计算。出于这个原因,最初的Java虚拟机规范要求所有的中间计算都截短。数学团体不喜欢这样。不仅截短指令会导致溢出,而且这实际上会比更精确的计算要慢,因为截短操作要花费时间。出于这个原因,Java编程语言在承认最优性能和完美的可重复性之间相矛盾的要求方面进行了更新(译者:翻译水平有限,不知所云)。在默认情况下,虚拟机的设计者现在被允许在计算的中间过程中使用扩展精度。但是,带有关键字strictfp特征标记的方法必须使用严格的浮点运算以得到可重复的结果。例如,你可以像这样标记main

 

public static strictfp void main(String[] args)

 

Then all instructions inside the main method use strict floating-point computations. If you tag a class as strictfp, then all of its methods use strict floating-point computations.

那么所有在main方法内部的指令都将用严格的浮点运算。如果你将类标记成strictfp,那么它所有的方法都将是用严格的浮点运算。

The gory details are very much tied to the behavior of the Intel processors. In default mode, intermediate results are allowed to use an extended exponent, but not an extended mantissa. (The Intel chips support truncation of the mantissa without loss of performance.) Therefore, the only difference between default and strict mode is that strict computations may overflow when default computations don't.

依赖Intel处理器的性能的耸人听闻的资料非常的多(译者:翻译水平有限,不知所云)。在默认模式下,中间结果允许使用扩展的指数,而不是扩展的尾数。(Intel芯片支持再不损失性能的前提下的尾数阶段。)因此,默认模式和严格模式的唯一区别就是严格运算可能溢出的时候,默认运算不会溢出。

If your eyes glazed over when reading this note, don't worry. Floating-point overflow isn't a problem that one encounters for most common programs. We don't use the strictfp keyword in this book.

如果当你读到这个注释的时候两眼放光,不要担心(译者:翻译水平有限,不知所云)。浮点溢出并不是在大多数通用程序中都能够遇到的问题。我们不会在这本书中用到strictfp这个关键字。

 

Increment and Decrement Operators

递加和递减运算符

Programmers, of course, know that one of the most common operations with a numeric variable is to add or subtract 1. Java, following in the footsteps of C and C++, has both increment and decrement operators: n++ adds 1 to the current value of the variable n, and n-- subtracts 1 from it. For example, the code

程序员们当然知道对一个数字变量最普遍的操作之一就是加或是减1Java,参照CC++中的步长值,也有递加和递减运算符:n++在变量n的当前值上加1,而n--是在之上减1。例如,代码

 

int n = 12;
n++;

 

changes n to 13. Because these operators change the value of a variable, they cannot be applied to numbers themselves. For example, 4++ is not a legal statement.

使n变成13。因为这些运算符改变的是变量的值,他们并不适用于数字本身。例如,4++不是合法的语句。

There are actually two forms of these operators; you have seen the "postfix" form of the operator that is placed after the operand. There is also a prefix form, ++n. Both change the value of the variable by 1. The difference between the two only appears when they are used inside expressions. The prefix form does the addition first; the postfix form evaluates to the old value of the variable.

事实上这些运算符有两种运用格式;你在前面看到过的是将运算符放在操作数后面的“后缀”式。还有一种前缀式,++n。两种都是使变量的值改变1。两者的不同仅仅是在他们被用在表达式中的时候出现。前缀格式先进行累加;后缀格式则先取变量的原值。

 

int m = 7;
int n = 7;
int a = 2 * ++m; // now a is 16, m is 8 现在a是16,m是8
int b = 2 * n++; // now b is 14, n is 8 现在b是14,n是8

 

We recommend against using ++ inside other expressions because this often leads to confusing code and annoying bugs.

我们并不建议在其他表达式中使用++,因为这样常常会导致混乱的代码和恼人的bug

(Of course, while it is true that the ++ operator gives the C++ language its name, it also led to the first joke about the language. C++ haters point out that even the name of the language contains a bug: "After all, it should really be called ++C, because we only want to use a language after it has been improved.")

(当然,C++语言确实是因操作符++而得名的,但这时它也导致了第一个关于C++语言的笑话。痛恨C++的人指出,甚至这个语言的名字就包含一个bug:“毕竟,它其实应该被叫做++C,因为我们只希望在他被改良后再使用这个语言。”)

Relational and boolean Operators

关系和boolean运算符

Java has the full complement of relational operators. To test for equality you use a double equal sign, ==. For example, the value of

Java具有关系运算符的完整补充。测试相等关系要使用“双等于号” == 。例如,

 

3 == 7

 

is false.

的值是false

Use a != for inequality. For example, the value of

!= 表示不相等。例如,

 

3 != 7

 

is true.

的值是true

Finally, you have the usual < (less than), > (greater than), <= (less than or equal), and >= (greater than or equal) operators.

最后,你还可以使用常见的<(小于)、>(大于)、<=(小于等于)和 >=(大于等于)运算符。

Java, following C++, uses && for the logical "and" operator and || for the logical "or" operator. As you can easily remember from the != operator, the exclamation point ! is the logical negation operator. The && and || operators are evaluated in "short circuit" fashion. The second argument is not evaluated if the first argument already determines the value. If you combine two expressions with the && operator,

Java,参照C++,使用&&作为逻辑“与”运算符,||作为逻辑“或”运算符。与你很容易记住的!=运算符一样,感叹号!是逻辑非运算符。&&||运算符使用“短路”方式求值。如果第一个参数已经确定表达式的值,则第二个参数就不被求值了。如果你用&&运算符将两个表达式联起来,


expression
1 && expression2

and the truth value of the first expression has been determined to be false, then it is impossible for the result to be TRue. Thus, the value for the second expression is not calculated. This behavior can be exploited to avoid errors. For example, in the expression

并且第一个表达式的真值已经确定是false,则它就不可能得到TRue的结果。因此,第二个表达式的值就不被计算了。采用这种办法可以避免出错。例如,在表达式

 

x != 0 && 1 / x > x + y // no division by 0 避免被0除

 

the second part is never evaluated if x equals zero. Thus, 1 / x is not computed if x is zero, and no divide-by-zero error can occur.

中,只要x等于零,则第二个部分就永不会被求值。因此,如果x是零,1 / x就不会计算,也就不会发生被零除出错。

Similarly, the value of expression1 || expression2 is automatically true if the first expression is true, without evaluation of the second expression.

同样的,如果第一个表达式是true,就不会计算第二个表达式的值而自动得出expression1 || expression2的值true

Finally, Java supports the ternary ?: operator that is occasionally useful. The expression

最后,Java支持偶尔会用到的三元运算符?:。表达式


condition 
? expression1 : expression2

evaluates to the first expression if the condition is TRue, to the second expression otherwise. For example,

如果条件(condition)是TRue,则求第一个表达式的值,否则求第二个表达式。例如,

 

x < y ? x : y

 

gives the smaller of x and y.

给出xy中较小的。

Bitwise Operators

位运算符

When working with any of the integer types, you have operators that can work directly with the bits that make up the integers. This means that you can use masking techniques to get at individual bits in a number. The bitwise operators are

当你使用任何一种整数类型时,都可以使用能对组成整数的二进制位直接起作用的运算符。这意味着你可以通过掩码技术得到数字中特定的二进制位。位运算符是

 

& ("and")       | ("or")       ^ ("xor")        ~ ("not")

 

These operators work on bit patterns. For example, if n is an integer variable, then

这些运算符对二进制位结构起作用。例如,如果n是一个整型变量,那么

 

int fourthBitFromRight = (n & 8) / 8;

 

gives you a 1 if the fourth bit from the right in the binary representation of n is 1, and 0 if not. Using & with the appropriate power of 2 lets you mask out all but a single bit.

如果n的二进制表示的右数第四位是1,则得到1,否则是0。用&和适当的2的幂同时使用可以屏蔽掉除了特定位以外的所有二进制位。

NOTE

注释

When applied to boolean values, the & and | operators yield a boolean value. These operators are similar to the && and || operators, except that the & and | operators are not evaluated in "short circuit" fashion. That is, both arguments are first evaluated before the result is computed.

&|运算符应用于boolean值时,就会得到boolean值。这些运算符除了不用“短路”方式求值外,其它与&&||运算符一样。换句话说,在计算结果之前,两个参数都要先被求值。

There are also >> and << operators, which shift a bit pattern to the right or left. These operators are often convenient when you need to build up bit patterns to do bit masking:

还有>><<运算符,用来向右或向左移动二进制位结构。这些运算符经常会在建立用于位屏蔽的位结构时为你带来便利:

 

int fourthBitFromRight = (n & (1 << 3)) >> 3;

 

Finally, a >>> operator fills the top bits with zero, whereas >> extends the sign bit into the top bits. There is no <<< operator.

最后,>>>运算符用零来填充最高位,而>>扩展符号位到最高位中。没有<<<运算符。

CAUTION

警告

The right-hand side argument of the shift operators is reduced modulo 32 (unless the left-hand side is a long, in which case the right-hand side is reduced modulo 64). For example, the value of 1 << 35 is the same as 1 << 3 or 8.

移位运算符右侧参数是简化模数32(除非左侧是一个long类型,在这种情况下右侧是简化模数64)。例如,1 << 35的值和1 << 3或者8是一样的。

C++ NOTE

C++注释

In C/C++, there is no guarantee as to whether >> performs an arithmetic shift (extending the sign bit) or a logical shift (filling in with zeroes). Implementors are free to choose whatever is more efficient. That means the C/C++ >> operator is really only defined for non-negative numbers. Java removes that ambiguity.

C/C++中,并不确保>>完成的是算术移位(扩展符号位)还是逻辑移位(用零填充)。设备完全自由选择,无论哪一种更有效(译者:翻译水平有限,不知所云)。这意味着C/C++ >>运算符其实仅仅是为非负数定义的。Java消除了这种模糊。

 

Mathematical Functions and Constants

数学函数和常量

The Math class contains an assortment of mathematical functions that you may occasionally need, depending on the kind of programming that you do.

Math类包含一个分类的数学函数,你可能偶尔会用到,这取决于你所做的程序的类型。

To take the square root of a number, you use the sqrt method:

求一个数的平方根,你要用sqrt方法:

 

double x = 4;
double y = Math.sqrt(x);
System.out.println(y); // prints 2.0 打印输出2.0

 

NOTE

注释

There is a subtle difference between the println method and the sqrt method. The println method operates on an object, System.out, defined in the System class. But the sqrt method in the Math class does not operate on any object. Such a method is called a static method. You can learn more about static methods in Chapter 4.

println方法和sqrt方法之间有一个细微的差别。println方法对一个在System类中定义的对象System.out起作用。但在Math类中的sqrt方法不对任何对象起作用。这样的方法叫做静态方法。你会在第4章中学到关于静态方法的更多内容。

 

The Java programming language has no operator for raising a quantity to a power: you must use the pow method in the Math class. The statement

Java编程语言中没有计算乘方的运算符:你必须用Math类中的pow方法。语句

 

double y = Math.pow(x, a);

 

sets y to be x raised to the power a (xa). The pow method has parameters that are both of type double, and it returns a double as well.

y等于xa次幂(xa)。pow方法的两个参数都是double类型,并且返回的也是double类型。

The Math class supplies the usual trigonometric functions

Math类还提供了常见的三角函数

 

Math.sin
Math.cos
Math.tan
Math.atan
Math.atan2

 

and the exponential function and its inverse, the natural log:

以及指数函数和它的反函数,自然对数:

 

Math.exp
Math.log

 

Finally, two constants denote the closest possible approximations to the mathematical constants p and e:

最后,还有两个常量来表示最接近数学常量pe的可能近似值。

 

Math.PI
Math.E

 

TIP

提示

Starting with JDK 5.0, you can avoid the Math prefix for the mathematical methods and constants by adding the following line to the top of your source file:

JDK5.0开始,通过在源文件的最开始加上下面一行,你便可以在使用数学方法和常量时省略前缀Math

 

import static java.lang.Math.*;

 

For example,

例如,

 

System.out.println("The square root of /u03C0 is " + sqrt(PI));

 

We discuss static imports in Chapter 4.

我们在第4章讨论静态输入。

 

NOTE

注释

The functions in the Math class use the routines in the computer's floating-point unit for fastest performance. If completely predictable results are more important than fast performance, use the StrictMath class instead. It implements the algorithms from the "Freely Distributable Math Library" fdlibm, guaranteeing identical results on all platforms. See http://www.netlib.org/fdlibm/index.html for the source of these algorithms. (Whenever fdlibm provides more than one definition for a function, the StrictMath class follows the IEEE 754 version whose name starts with an "e".)

Math类中的函数使用计算机浮点单元里的例程以得到最快的性能。如果完全可重复的结果比快速的性能更重要的话,可以改用StrictMath类。它执行“自由可分类数学库” fdlibm中的算法,保证在所有的平台上都得到相同的结果。这些算法的源代码参见http://www.netlib.org /fdlibm/index.html 。(只要fdlibm为函数提供了不只一个定义,StrictMath类都要参照名字以“e”开头的IEEE 754版本(译者:翻译水平有限,不知所云)。

 

Conversions Between Numeric Types

数值类型间的转换

It is often necessary to convert from one numeric type to another. Figure 3-1 shows the legal conversions.

从一种数值类型转换到另一种数值类型是常常需要做的。图3-1所示为合法转换。

Figure 3-1. Legal conversions between numeric types

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

 

The six solid arrows in Figure 3-1 denote conversions without information loss. The three dotted arrows denote conversions that may lose precision. For example, a large integer such as 123456789 has more digits than the float type can represent. When the integer is converted to a float, the resulting value has the correct magnitude but it loses some precision.

3-1中的六个实线箭头表示无信息丢失的转换。三个虚线箭头表示转换可能丢失精度。例如,像123456789这样的长整型数比float类型所能代表的数字要多。当一个整型数转换成float时,得到的值虽然数量级正确,但丢失了一些精度。

 

int n = 123456789;
float f = n; // f is 1.23456792E8  f是1.23456792E8

 

When two values with a binary operator (such as n + f where n is an integer and f is a floating-point value) are combined, both operands are converted to a common type before the operation is carried out.

当两个值用二元运算符(就像n + f,这里n是整型数而f是浮点数)组合起来的时候,两个操作数在运算完成前都被转换成一个公共的类型。

·         If either of the operands is of type double, the other one will be converted to a double.

·         如果任一个操作数是double类型,则另一个被转换成double类型。

·         Otherwise, if either of the operands is of type float, the other one will be converted to a float.

·         否则,如果任一个操作数是float类型,则另一个被转换成float类型。

·         Otherwise, if either of the operands is of type long, the other one will be converted to a long.

·         否则,如果任一个操作数是long类型,则另一个被转换成long类型。

·         Otherwise, both operands will be converted to an int.

·         否则,两个操作数都被转换成int类型。

Casts

强制转换

In the preceding section, you saw that int values are automatically converted to double values when necessary. On the other hand, there are obviously times when you want to consider a double as an integer. Numeric conversions are possible in Java, but of course information may be lost. Conversions in which loss of information is possible are done by means of casts. The syntax for casting is to give the target type in parentheses, followed by the variable name. For example:

在前面一节,你看到int值在必要的时候会自动转换成double值。另一方面,显然你也有要将一个整数看成是double类型的时候。数值转换在Java中是可能的,但当然信息可能会丢失。可能会使信息丢失的转换依靠强制转换来完成。强制转换的语法是将目标类型放在圆括号中,后面紧接变量名。例如:

 

double x = 9.997;
int nx = (int) x;

 

Then, the variable nx has the value 9 because casting a floating-point value to an integer discards the fractional part.

于是,变量nx的值是9,因为将一个浮点值强制转换成一个整数而放弃小数部分。

If you want to round a floating-point number to the nearest integer (which is the more useful operation in most cases), use the Math.round method:

如果你想要将一个浮点数舍入到最接近的整数(这在大多数情况下都比较有用),就用Math.round方法:

 

double x = 9.997;
int nx = (int) Math.round(x);

 

Now the variable nx has the value 10. You still need to use the cast (int) when you call round. The reason is that the return value of the round method is a long, and a long can only be assigned to an int with an explicit cast because there is the possibility of information loss.

现在变量nx的值是10。当你调用round时,仍然需要使用强制转换(int)。原因是round方法返回的值是long类型,而long类型只能通过明确的强制转换被赋值给一个int类型,因为这有信息丢失的可能。

CAUTION

警告

If you try to cast a number of one type to another that is out of the range for the target type, the result will be a truncated number that has a different value. For example, (byte) 300 is actually 44.

如果你试图将一个类型的超出目标类型取值范围的数强制转换成另一个类型,得到的结果就是一个被截短而具有不同值的数。例如,(byte) 300实际上是44

 

C++ NOTE

C++注释

You cannot cast between boolean values and any numeric type. This convention prevents common errors. In the rare case that you want to convert a boolean value to a number, you can use a conditional expression such as b ? 1 : 0.

你不能在boolean值和任意的数值类型之间强制转换。这个约定可以防止公共错误。在极少碰到的要将boolean值转换成数的情况下,你可以使用像b ? 1 : 0这样的表达式。

 

Parentheses and Operator Hierarchy

括号和运算层级

Table 3-4 shows the precedence of operators. If no parentheses are used, operations are performed in the hierarchical order indicated. Operators on the same level are processed from left to right, except for those that are right associative, as indicated in the table. For example, because && has a higher precedence than ||, the expression

3-4所示为运算优先级。如果没有使用括号,则操作按照层级顺序所示去执行。同一层级的运算从左到右执行,除了那些表中指出右关联的之外。例如,因为&&具有比||较高的优先权,表达式

 

a && b || c

 

Table 3-4. Operator Precedence

3-4. 操作符优先级

Operators

运算符

Associativity

结合性

[] . () (method call 方法调用)

Left to right

! ~ ++ -- + (unary 一元) (unary一元) () (cast 强制转换) new

Right to left

* / %

Left to right

+ -

Left to right

<< >> >>>

Left to right

< <= > >= instanceof

Left to right

== !=

Left to right

&

Left to right

^

Left to right

|

Left to right

&&

Left to right

||

Left to right

?:

Right to left

= += -= *= /= %= &= |= ^= <<= >>= >>>=

Right to left

 

means

意思是

 

(a && b) || c

 

Because += associates right to left, the expression

因为+=是从右到左结合的,表达式

 

a += b += c

 

means

意思是

 

a += (b += c)

 

That is, the value of b += c (which is the value of b after the addition) is added to a.

也就是说,b += c的值(即做完加法后的b值)加到a上。

C++ NOTE

C++注释

Unlike C or C++, Java does not have a comma operator. However, you can use a comma-separated list of expressions in the first and third slot of a for statement.

CC++不同,Java没有逗号运算符。然而,你可以在for语句的第一和第三段用逗号分隔表达式列表。

 

Enumerated Types

枚举类型

Sometimes, a variable should only hold a restricted set of values. For example, you may sell clothes or pizza in four sizes: small, medium, large, and extra large. Of course, you could encode these sizes as integers 1, 2, 3, 4, or characters S, M, L, and X. But that is an error-prone setup. It is too easy for a variable to hold a wrong value (such as 0 or m).

有时,一个变量仅需要保留一组限定的值。例如,你可能卖四种尺寸的衣服或是比萨饼:小号、中号、大号和特大号。当然,你可以将这些号码用整数1234或字符S M L、和 X来编码。但这是个容易出错的设置。对于一个变量,非常容易得到一个错误的值(就像0或者是m)。

Starting with JDK 5.0, you can define your own enumerated type whenever such a situation arises. An enumerated type has a finite number of named values. For example,

JDK5.0开始,只要发生这种情况,你就可以定义你自己的枚举类型。一个枚举类型具有有限个指定的值。例如,

 

enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };

 

Now you can declare variables of this type:

现在你可以声明这种类型的变量:

 

Size s = Size.MEDIUM;

 

A variable of type Size can hold only one of the values listed in the type declaration or the special value null that indicates that the variable is not set to any value at all.

一个Size类型的变量只能保留类型声明列表中的某一个值,或者表示变量根本没有被设定任何值得特殊值null

We discuss enumerated types in greater detail in Chapter 5.

我们在第5章会更详细的讨论枚举类型。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值