参考自 – 《Java核心技术卷1》
运算符
在Java中,使用算术运算符 +、-、*、/ 表示加、减、乘、除运算。
当参与的两个操作数都是整数时,表示整数除法;否则,表示浮点数除法。如:15.0/2=7.5,15/2=7。
整数的求余操作(也称取模)用 % 表示。如:15%2=1。
注:整数被0除将会产生一个异常;而浮点数被0除将会得到无穷大或 NaN 结果。
1 数学函数与常量
在 Math 类中,包含了各种各样的数学函数。如:
double x = 4;
double y = Math.sqrt(x); // sqrt()为计算平方根函数
System.out.println(y); //输出结果为 2
在Java中,没有幂运算,可以借助 Math 类的 pow 方法:
double y = Math.pow(x,a); // 幂运算
将 y 的值设置为 x 的 a 次幂(x^a)。pow 方法有两个 double 类型的参数,返回结果也为 double 类型。
Math 类提供了一些常用的三角函数:
Math.sin
Math.cos
Math.tan
Math.atan
Math.atan2
还有指数函数等
Math.log
Math.exp
常用的常量的近似值:
Math.PI //圆周率
Math.E //e
导入 Math 包(导入包之后就不需要加前缀 “Math” 即可使用数学函数和常量):
import static java.lang.Math.*
2 数值类型之间的转换
数值类型之间合法的转换(实线表示无信息丢失的转换,虚线表示可能有精度损失的转换):
精度损失示例:
int n = 123456789;
float f = n; // f等于1.23456792E8
当进行二元操作时,先要将两个操作数转换为同一种类型,然后再进行计算:
- 如果两个操作数中有一个是double类型,另一个操作数就会转换为double类型
- 否则,如果其中一个操作数是float类型,另一个操作数将会转换为float类型
- 否则,如果其中一个操作数是long类型,另一个操作数将会转换为long类型
- 否则,两个操作数都将被转换为int类型
注:以上均为自动转换。
3 强制类型转换(cast)
强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名:
double x = 9.997;
int nx = (int)x; //nx为9(强制类型转换通过截断小数部分将浮点值转换为整型)
如果相对浮点数进行舍入运算,以便得到最接近的整数(很多情况下,这种操作更有用),那就需要使用 Math.round 方法:
double x = 9.997;
int nx = (int)Math.round(x); //显然,结果nx等于10(round()方法返回的结果为long类型)
注:如果试图将一个数值从一种类型强制类型转换为另一种类型,而又超过了目标类型的表示范围,结果就会截断成一个完全不同的值。例如,(byte)300的实际值为44。
注:不要在boolean类型与任何数值类型之间进行强制类型转换,这样可以防止发生错误。若要进行转换,可以使用条件表达式 b?1:0 。
4 运算符
4.1 结合赋值和运算符
在赋值中使用的二元运算符,是一种很方便的简写方式(一般的,要把运算符放在=左边,如 *=或%=):
x += 4;
等价于:
x = x + 4;
注:如果运算符得到一个值,其类型与左侧操作数的类型不同,就会发生强制类型转换。例如:假如x是一个int,则以下语句:
x += 3.5;
是合法的,它会自动将 x 设为 (int)(x+3.5)。
4.2 自增与自减运算符
自增、自减为简单的加1、减1:
int n = 11;
n--; // n等于10
n++; // n等于12
注:由于这些运算符会改变变量的值,所有它们的操作数不能是数值。例如,4++就不是一个合法的语句。
实际上,这些运算符有两种形式:“前缀”形式(++n),“后缀”形式(n++)。
无论前缀形式还是后缀形式都会使变量加1或减1.但在表达式中时,二者就有区别了:
int m = 7;
int n = 7;
int a = 2 * (++m); //a=16,m=8
int b = 2 * (n++); //a=14,n=8
建议不要在表达式中使用 ++ ,因为这样的代码很容易让人困惑,而且会带来烦人的 bug.
4.3 关系和boolean运算符
Java包含丰富的关系运算符。比如:==,<,>,<=和>=,其结果值为true或false.
其中,使用&&表示逻辑“与”运算符,||表示逻辑“或”运算符,感叹号!表示逻辑“非”运算符。
注:&&和||运算符是按照“短路”方式来求值的:如果第一个操作数已经能够确定表达式的值,那么第二个操作数就不必计算了。如:
expression1 && expression2
如果第一个表达式的真值为false,那么结果就不可能为true。因此,第二个表达式就不必计算了。可以利用这一点来避免错误。如:
x != 0 && 1/x > x+y
如果x等于0,那么第二部分就不会计算。因此,如果x为0,也就不会计算1/x.除以0的错误就不会出现。
类似的,如果一个表达式为true, expression1 || expression2
的值就自动为true,而无须计算第二个表达式。
Java同样支持三元操作符:
condition ? expression1 : expression2
如果条件 condition 成立(true),则取 expression1 的值,否则取 expression2 的值.
4.4 位运算符
处理整型类型时,可以直接对组成整型数值的各个位完成操作。
位运算符包括:&(and) |(or) ^(xor) ~(not)
以上 a,b 都是整型类型。这些运算符按位模式处理。
注:应用在布尔值上时,&和|运算符也会得到一个布尔值。它们与&&和||运算符很类型,不过&和|运算符不采用“短路”方式来求值,也就是说,得到计算结果之前两个操作数都需要计算。
4.5 括号与运算符级别
同一级别的运算符按照从左到右的次序进行计算(除部分右结合运算符外)
运算优先级:
4.6 枚举类型
有时候,变量的取值只在一个有限的集合内。例如,衣服的尺寸有小、中、大和超大四种,此时,尺寸便是集合,小、中、大、超大即为集合的元素。但这样存在一定的隐患(在变量中很可能保存的是一个错误的值)。
针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。如:
enmu Size {SMALL,MEDIUM,LARGE,EXTRA_LARGE} //枚举类型不能是本地类型
Size s = Size.MEDIUM;
只在一个有限的集合内。例如,衣服的尺寸有小、中、大和超大四种,此时,尺寸便是集合,小、中、大、超大即为集合的元素。但这样存在一定的隐患(在变量中很可能保存的是一个错误的值)。
针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。如:
enmu Size {SMALL,MEDIUM,LARGE,EXTRA_LARGE} //枚举类型不能是本地类型
Size s = Size.MEDIUM;
Size类型的变量只能存储这个类型声明中给定的某个枚举值,或者null值(null表示这个变量没有设置任何值)