赋值运算符
与大部分编程语言相同,Java使用'='运算符来进行赋值操作,这种操作会将右边的计算结果(成为右值)赋值给左边的变量。
右值可以为任意常数、变量或表达式而左值必须为一个明确的变量。如:
a = 4 + 3;
下面的表达式是不能编译通过的:
4 + 3 = a;
因为我们不能将任何东西赋给常数。
在Java中,使用'=
'对一个对象进行赋值时,真正操作的是它的引用,即是对对应的引用进行拷贝。这也正是上一节内容中引用类型的含义。
比如:
Blog blog = new Blog("天码营的博客", "这是我的第一篇博客"); Blog blogB = blog; // 这表示blogB和blog指向同一篇博客
接下来我们来了解一下都有哪些算数运算符,讲解过程中会涉及到一些简单的代码。我们可以将这些代码拷贝HelloWorld
类的main
函数中执行来查看效果。
注意一个方法内的变量名是不能重复的,查看某个变量的值,将其传入System.out.println()
方法中即可。
算数运算符
Java提供了包括加减乘除、取模在内的算数运算符。
以加法运算为例,如果我们要将x
变量的值增加4,可以这样写:
`x = x + 4;`
Java提供了同时进行算数运算和赋值的运算符,可以这样写:
x += 4;
这一行代码与上一行代码是等价的。
其他算数运算符'*
', '/
', '-
', '%
',对应的赋值运算符分别为'*=
','/=
','-=
','%=
'。
Java也提供了自增自减运算符'--
'和'++
'来使编码更为简洁,它们分别表示增加1
和减少1
:
a++;a += 1;a = a + 1;a--;a -= 1;a = a - 1;
上面的代码中,前三行代码完全等价,后三行代码也完全等价。
关系运算符
关系运算符生成布尔(boolean
)类型的结果,即返回true
或者false
。
关系操作符包括:
> : 大于 <:小于 ==:等于 !=:不等于 >=:大于等于 <=:小于等于
'==
'和'!=
'适用于所有类型的对象,其他关系运算符并不适用于布尔类型的值,因为它们只有true
或false
,大于和小于并无实际意义。
'==
'和'!=
'作为关系运算符只用来比较对象的引用,如果想比较两个对象实际内容是否相同,需要调用对象的equals()方法。
逻辑运算符
逻辑运算符的结果和操作的对象均为布尔值。
逻辑操作符包括:
&&:与 ||:或 !:非
比如说我们要通过编程计算y = |x * (x - 1)|
这个表达式的值,我们即可使用逻辑运算符进行运算:
int y = 0;if (x >= 1 || x <= 0) { y = x * (x - 1);} else { y = -x * (x - 1);}
在Java中,逻辑运算符支持短路操作,一旦能够明确表达整个表达式的值,我们就不需要计算表达式的余下部分了。比如我们需要判断一个对象不为空且它的某个方法返回值不为空,我们就可以这样判断:
if (object != null && object.someFunction() != null) { // do something.}
如果object
为空,第一部分表达式object != null
会返回false
,那么不管&&
运算符后面的表达式object.someFunction() != null
的结果如何,最终的值都为false。编译器会自动将这部分运算进行优化,不会执行object.someFunction() != null
。
位运算符
位运算符面向的运算对象是二进制的“位”,可应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型,运算时会将其对应Bit位(0或者是1)进行布尔代数运算或者移动操作。
& 与运算:对于某一位,只要两个操作数都为1,则该位的结果为1,否则为0
| 或运算:对于某一位,只要两个操作数有一个为1,则该位的结果为1,否则为0
^异或运算:对于某一位,如果两个操作数不相同,则该位的结果为1,否则为0
~非运算:按位补运算符翻转操作数的每一位
<<二进制左移运算符:左操作数按位左移右操作数指定的位数
>>二进制右移运算符:左操作数按位右移右操作数指定的位数
>>>二进制右移补零操作符:左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充
计算逻辑的描述读起来有些晦涩,我们通过例子可以更清晰得了解位运算符如何进行计算。假设如果x
等于60;y
等于13;则它们的二进制表示,以及位运算的结果如下所示:
x = 0011 1100y = 0000 1101-----------------x & y = 0000 1100x | y = 0011 1101x ^ y = 0011 0001~x = 1100 0011 x << 2 = 1111 0000x >> 2 = 0000 1111x >>> 2 = 0000 1111
注意>>
和>>>
的区别:
右移位运算符
>>
,若操作的值为正,则在高位插入0;若值为负,则在高位插入1;右移补零操作符
>>>
,无论正负,都在高位插入0。
三元运算符
三元运算符
Java中的条件运算符是一个三元运算符,它的形式如下:
booleanExpression ? valueWhenTrue : valueWhenFalse
如果布尔表达式值为true,则表达式的值为valueWhenTrue
的值,否则为valueWhenFalse
的值。
比如我们要计算x
的绝对值,可以通过如下代码实现:
if (x >= 0) { y = x;} else { y = -x;}
通过三元运算符,只需要一条语句y = x >= 0 ? x : -x;
就可以完成,更为简洁。
类型转换运算符
我们在很多情况下会用到类型转换。在适当的时候,Java也会根据数据类型将数据类型自动转为另一种。比如我们为float
变量赋一个整数值,编译器会将int
转化为float
赋给变量。
但是在很多情况下,Java并不能判断我们是否需要进行类型转换,这时就需要类型转化运算符,它允许我们显式地进行类型转换,如:
int a = 10;long b = (long) a;long c = (long) 100;
我们对变量和常量都能进行类型转换。
在对浮点数进行类型转换时,我们需要注意截尾的问题。如我们要将10.9进行类型转换:(int) 10.9
,它的值并不是四舍五入的11,而是10。
各个运算符的优先级
运算符优先级决定一个表达式里术语的分组。它影响着一个表达式如何求值。一定的运算符比其他运算符拥有更高的优先级。
例如:乘法运算符比加法运算符有更高的优先级,表达式1 + 5 * 6
,根据运算符的优先级,编译器会先计算5 * 6
,再计算30 + 1
,最终得到结果31
。
绝大多数情况下,表达式本身就很容易看得出优先级,比如赋值运算肯定是优先级最低的。在对优先级不太明确的情况下,我们使用括号就能按照我们希望的方式来改变优先级,所以不需要对运算符优先级做太多记忆。