• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

《Java从入门到失业》第三章:基础语法及基本程序结构(3.7):运算符(自增自减、关系运算、逻辑运算、条件运算、位运算、赋值运算、类型转换)

开发技术 开发技术 3周前 (08-31) 25次浏览

3.7运算符

3.7.2自增自减运算符

       在程序中,变量的加1、减1操作是经常会碰到的。Java和其他语言一样,给我们提供了自增、自减运算符来方便的完成这些操作。“++”表示自增,“–”表示自减。我们看一个例子:

int a = 3;  
a++;  
System.out.println(a);// 结果是4  
int b = 8;  
b--;  
System.out.println(b);// 结果是7  

自增自减运算符会改变变量的值,因此它们的操作数不能是数值。例如5++就是一条非法的语句。另外这2个运算符还有另外一种形式,就是放在操作数的前面,我们看一个例子:

int a = 3;  
++a;  
System.out.println(a);// 结果是4  
int b = 8;  
--b;  
System.out.println(b);// 结果是7 

另外,我们还可以把变量和自增自减运算符当做一个整体,参与到赋值语句或者是运算表达式中。例如:

int a1 = 3;  
int b = a1++;  
int a2 = 3;  
int c = ++a2;  
int a3 = 3;  
int d = a3++ * 5;  
int a4 = 3;  
int e = ++a4 * 5;  
System.out.println(b);// 结果是3  
System.out.println(c);// 结果是4  
System.out.println(d);// 结果是15  
System.out.println(e);// 结果是20  

我们可以看到,无论是赋值语句,还是运算表达式,当++在操作数后面的时候,都是先赋值或先参与运算,然后再自己增加1。当++在操作数前面的时候,都是先自己增加1,再赋值或参与运算。对于自减也是一样。可以总结一个规律:运算符在前面时先起作用,运算符在后面时后起作用。

  这里有一个小笑话,我们都知道C++语言,这门语言把++运算符用到语言命名上了,本意是C语言的扩展。但是根据运算法则,运算符在后面后起作用,因此反对C++的程序员说我们使用的它的时候还没起作用呢,应该命名为++C才对。

3.7.3关系运算符

  前面的运算符对应数学中的加减乘除取余等运算,关系运算符对应的是比较2个数的关系,关系有等于、不等于、大于、大于等于、小于和小于等于。列表如下:

运算符

表达式

结果(假设a=15,b=10)

==

a==b

false

!=

a!=b

true

a>b

true

>=

a>=b

true

a<b

false

<=

a<=b

false

使用和结果都很简单,没什么可讲的。

3.7.4逻辑运算符

       逻辑运算包括3个:逻辑与、逻辑或、逻辑非,对应的运算符和说明如下:

运算符

表达式

说明

&&

expression1 && expression2

逻辑与。当且仅当两个操作数都为真,条件才为真

||

expression1 || expression2

逻辑或。如果任何一个为真,条件为真。

!

!expression1

逻辑非。用来反转操作数的逻辑状态。

例如:

boolean a = true;  
boolean b = false;  
boolean c = a && b;// 结果是false  
boolean d = a || b;// 结果是true  
boolean e = !a;// 结果是false

需要注意的是,逻辑与和逻辑或都是采用“短路”的方式进行运算的。就是某一个表示的结果已经能够确定整个运算表达式的结果的时候,剩下的表达式就不用再进行计算了。

例如:

int a = 5;  
boolean b = (a < 4) && (a++ < 10);// a<4结果是false,整个表达式结果就是false,因此a++不会运算,a的值依然是5  
  
int c = 5;  
boolean d = (c < 6) || (c++ < 10);// c<6结果是true,整个表达式结果就是true,因此a++不会运算,c的值依然是5

3.7.5条件运算符

  条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量,表达式为:

condition ? expression1 : expression2

当条件condition为真时,计算expression1并返回,否则计算expression2并返回。

例如:

int a = 5;  
int b = 10;  
int c = 20;  
int d = a < b ? c + a : c + b;// a<b结果是true,因此d=c+a=25

3.7.6位运算符

       在Java中,处理整型数值时,可以直接对数值的二进制的各个位进行操作,我们先列一个表,然后再进行例子演示:

操作符

说明

&

按位与操作符。如果相对应位都是1,则结果为1,否则为0

|

按位或操作符。如果相对应位都是0,则结果为0,否则为1

^

按位异或操作符。如果相对应位值相同,则结果为0,否则为1

~

按位取反操作符。翻转操作数的每一位,即0变成1,1变成0

<< 

按位左移运算符。左操作数按位左移右操作数指定的位数

>> 

按位右移运算符。左操作数按位右移右操作数指定的位数

>>> 

按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。

我们看一个例子:

int a = 55; // 二进制为 0011 0111  
int b = 18; // 二进制为 0001 0010  
int c = a & b;// 结果二进制为 0001 0010,18  
int d = a | b;// 结果二进制为 0011 0111,55  
int e = a ^ b;// 结果二进制为0010 0101,37  
int f = ~a;// 结果二进制为 1100 1000,-56  
int g = a << 2;// 结果二进制为 1101 1100,220  
int h = a >> 2;// 结果二进制为 0000 1101,13  
int i = a >>> 2;// 结果二进制为 0000 1101,13 

对于按位与&运算,有个小技巧,就是可以快速判断一个整数m的二进制从右往左数第n位是否为1,判断方法为看m&2n-1的值,值为0,则第n位为0,值为2n-1,则第n为为1。

对于<<运算,要注意几点:

  1. 对byte、short、char型进行左移运算,移位之前,它们会自动转换为int
  2. 右侧的参数,需要进行模32运算,其实就是保证右侧的参数小于32(当左侧是long,则模64,保证右侧的参数小于64),因为左移超过32没有意义。
  3. 因为右侧参数不可能超过32(64),所以其实符号位是不变的。
  4. 左移n位,其实相当于乘以2n(由十进制转二进制公式可以得出)

例如:

20的二进制补码:0001 0100,左移两位后:0101 0000,结果是80  

-20的二进制补码:1110 1100,左移两位后:1011 0000,结果是-80

对于>>运算,需要注意几点:

  1. 右移是带符号移动的,即如果是正数,高位补0,如果负数,高位补1
  2. 右移n位,相当于除以2n取整

例如:

20的二进制补码:0000 0000 0000 0000 0000 0000 0001 0100

右移两位后:0000 0000 0000 0000 0000 0000 0000 0101,结果是5

-20的二进制补码:1111 1111 1111 1111 1111 1111 1110 1100

右移两位后:1111 1111 1111 1111 1111 1111 1111 1011,结果是-5

对于>>>运算,需要注意几点:

  1. 右移是不带符号的,即不管正负,高位都补0

例如:

20的二进制补码:0000 0000 0000 0000 0000 0000 0001 0100

右移两位后:0000 0000 0000 0000 0000 0000 0000 0101,结果是5

-20的二进制补码:1111 1111 1111 1111 1111 1111 1110 1100

右移两位后:0011 1111 1111 1111 1111 1111 1111 1011,结果是1073741819

 3.7.7赋值运算符

       Java还支持把一些二元运算符和赋值符号联合起来使用,我们把它们称为赋值运算符,归结如下:

操作符

说明

举例

+=

左操作数加右操作数,结果赋值给左操作数

C += A即C = C + A

-=

左操作数减右操作数,结果赋值给左操作数

C -= A即C = C – A

*=

左操作数乘右操作数,结果赋值给左操作数

C *= A即 C = C * A

/=

左操作数除以右操作数,结果赋值给左操作数

C /= A即C = C / A

%=

左操作数对右操作数取模,结果赋值给左操作数

C %= 2即C = C % 2

<<=

左操作数左移右操作数,结果赋值运算符

C <<= 2即C = C << 2

>>=

左操作数右移右操作数,结果赋值运算符

C >>= 2即C = C >> 2

>>>=

左操作数右移右操作数,结果赋值运算符

C >>>= 2即C = C >>> 2

&=

左操作数和右操作数按位与,结果赋值给左操作数

C &= 2即C = C & 2

^=

左操作数和右操作数按位异或,结果赋值给左操作数

C ^= 2即C = C ^ 2

|=

左操作数和右操作数按位或,结果赋值给左操作数

C |= 2即C = C | 2

3.7.8运算优先级

       Java可以在一个表达式中进行多个运算,这就涉及到运算符优先级问题了。下表按优先级从高到底给出运算符的排序(排在一行的优先级相同):

操作符

结合性

[] 、()、 .(点操作符)

从左向右

++、–、 +(一元运算)、-(一元运算)、!、~

从右向左

*、/、%

从左向右

+、-

从左向右

<<、>>、.>>>

从左向右

<、<=、>、>=

从左向右

==、!=

从左向右

&

从左向右

^

从左向右

|

从左向右

&&

从左向右

||

从左向右

?:

从右向左

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

从右向左

是不是看着头都大了?笔者也头大,笔者强烈不推荐在一个表达式中使用多个运算符,可读性太差了。

3.7.9数值类型转换

       在程序的运行过程中,经常会碰到一种数值转换为另一种数值类型。有时候是程序自动转换的,有时候是我们用代码显性转换的。下图列出了数值类型转换的过程:

 《Java从入门到失业》第三章:基础语法及基本程序结构(3.7):运算符(自增自减、关系运算、逻辑运算、条件运算、位运算、赋值运算、类型转换)

需要注意的是,对于int转float、long转float,long转double,是可能会丢失精度的。例如:

int n = 123456789;  
float f = n;// n包含的位数比float多,结果f为1.23456792E8

3.7.9.1自动类型转换

       自动类型转换经常发生在2个不同类型操作数进行二元操作时。例如:

int n = 123;  
float f = 456.3f;  
float ff = n + f;// 自动将n转换为float,然后相加,结果是579.3  

对于这种自动转换,遵循如下规则:

  • 如果两个操作数中有一个double,则另一个会转换为double。
  • 否则如果有一个操作数是float,另一个会转换为float。
  • 否则如果有一个操作数是long,另一个会转换为long。
  • 否则两个操作数都被转换为int。

3.7.9.2强制类型转换

       上面我们知道了自动类型转换,有时候我们想把double转换为int,可以吗?Java中是允许这种数值转换的,方法就是用强制类型转换,但是会丢失精度。强制类型转换的格式为:

(type)value

type是最终想要的类型,value是被强制转换的原数值,例如:

float f = 456.3f;  
int nf = (int) f;// 截断小数部分,结果是456

需要注意的是,如果将一个数值从一种类型转换为另一种类型,但是又超出目标类型的范围,结果就会无法预料。例如把300转换为byte类型:

byte b = (byte) 300;// 结果是44  

喜欢 (0)