赋值运算符

与大部分编程语言相同,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

关系操作符包括:

 > : 大于   <:小于   ==:等于   !=:不等于  >=:大于等于  <=:小于等于

 

'=='和'!='适用于所有类型的对象,其他关系运算符并不适用于布尔类型的值,因为它们只有truefalse,大于和小于并无实际意义。

'=='和'!='作为关系运算符只用来比较对象的引用,如果想比较两个对象实际内容是否相同,需要调用对象的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

绝大多数情况下,表达式本身就很容易看得出优先级,比如赋值运算肯定是优先级最低的。在对优先级不太明确的情况下,我们使用括号就能按照我们希望的方式来改变优先级,所以不需要对运算符优先级做太多记忆。