首先了解什么是操作数、运算符、表达式。如下

  1. int a = 1;
  2. int b = 2;
  3. /*
  4. * a + b 这个整体叫表达式
  5. * a 和 b 这两个变量叫操作数
  6. * + 号叫运算符/操作符
  7. */
  8. int c = a + b;

分类:
运算符大致分类下面几类

  • 算数运算符 + - * / %
  • 字符串连接符 +
  • 关系运算符 > >= < <= == !=
  • 自增自减运算符 ++ —
  • 逻辑运算符 && || !
  • 移位运算符 << >> >>>
  • 位运算符 & | ^ ~
  • 条件运算符(三目运算符) ?:
  • 赋值运算符 + += -= *= /= %=

1.算数运算符

包括加+减-乘*除/取余%

1.1加 +

1.1.1可当字符串连接符

+号两边的操作数只要有一个是字符串,+号作为字符串连接符处理

1.1.2可当加法运算符

+号两边的操作数都是数值时,+号作为算数运算符处理

两个不同类型的操作数相加后的结果类型会变

规则如下(该规则也同样适用于减法)

  • 如果其中一个操作数是 double 类型,另一个操作数也会被转换为 double 类型
  • 否则,如果其中一个操作数是 float 类型,另一个操作数也会被转换为 float 类型
  • 否则,所有操作数都会被转换为 int 类型

  1. byte b = 2;
  2. // 两个数会被自动转换成 int,表达式的结果是 int,无法赋值给 byte 变量,因此编译错误
  3. b = 2 + b;
  4. // 解决办法
  5. //1.将类型为int的结果强转
  6. b = (byte)(2 + b);
  7. //2.使用符合运算符
  8. b += 2; // 不仅简化了写法,还自动将结果强转

1.2除 /

1.2.1当两个整数相除时,丢弃小数部分

  1. System.out.println(5 / 2); // 结果为2

解决办法

将任意其中一个操作数乘以1.0(推荐)

  1. System.out.println(5 / 2 * 1.0); // 结果为2.5

事先使用强制转换(有数据丢失风险)

将任意其中一个操作数强制转换为浮点数类型(用 float / double 都可以)

  1. System.out.println(5 / (double)2); // 结果为2.5

2.移位运算符

2.1左移 <<

2.1.1概念

将二进制中的每一位都往左移 x 位,右侧出现的空位用 0 代替。

2.1.2示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test1 = 1;
  4. System.out.println(test1 = test1 << 1); // 往左移动 1 位,结果为 2
  5. }
  6. }
  7. // 符号是 <<,可以简写为 <<=

步骤如下:
1.变量 test1 的值为 1,转换成二进制是 0000 0001
2.所有位往左移动 1 位
啊啊啊.png
3.将结果 0000 0010 转换成十进制就是 2

2.2带符号右移 >>

2.2.1概念

将二进制中的每一位都往右移 x 位,左侧出现的空位用原本第一位的值代替。

2.2.2示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test1 = -127; // 二进制为 1000 0001
  4. System.out.println(test1 = test1 >> 1); // 向右移动一位后为 1100 0000,十进制为 -64
  5. }
  6. }
  7. // 符号是 >>,可以简写为 >>=

步骤如下:
1.变量 test1 的值为 -127,转换成二进制是 1000 0001
2.所有位往右移动 1 位,由于这个是有符号右移,因此最左边的空白处用原来的第一位填充
生生世世.png
3.转换成十进制结果为 -64

2.3无符号右移 >>>(总是补0)

2.3.1概念

也叫逻辑右移运算符。
将二进制中的每一位都往右移 x 位,左侧出现的空位用 0 填充
使用>>> 进行使用

3.位运算符

位运算符,是用来操作的运算符,这个位,就是 1个字节(Byte)等于8个位(Bit/比特) 这句话里的位,每一个位只有两个值,0 和 1,位运算符,就是用来对位里的 0 和 1 进行各种操作的运算符。

3.1.按位取反 ~

3.1.1概念

简单来说,就是将每一位设置为相反的值。

用十进制的 1 举例,对应的二进制是 0000 0001,我们对他进行取反操作后,值就是 1111 1110,也就是把 0 变成 1,把 1 变成 0,就是这么简单,至于把他的值转换成十进制后值为多少,下面的示例中会涉及到。

3.1.2 示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test = 1;
  4. test = ~ test;
  5. System.out.println(test);
  6. }
  7. }
  8. // 结果为 -2

上面的代码运行后,结果为 -2(十进制)。

从上面举例的描述中可以得知,将十进制 1 取反后,二进制的值是 1111 1110,那么为什么将 1 位取反之后结果不是 -1 呢,就算是 -2,又该如何验证十进制的 -2 对应二进制的 1111 1110

为什么结果不为 -1?

根据目前已知的知识点,我最开始想的是,对 1 进行位取反之后可能是 -1,结果和我预期的并不一样。

我们这里进行的位取反和小时候学的对十进制数字直接取反是不一样的,十进制数字取反只有一个步骤就是改变最左边的符号。

而对十进制进行取反操作时,有三个步骤

  1. 1.十进制转换成二进制
  2. 2.对二进制取反
  3. 3.二进制转换成十进制

根据第二个步骤以及二进制十进制转换计算方式这两条来看,经过位取反后的十进制值和想象中的不一样也是很正常的了。

如何验证 -2 是否等于 1111 1110

首先需要知道的是,当十进制用二进制表示时,如 1 的二进制是 0000 0001, 从左边数的第一个位是符号位,用来表示该数是正数还是负数(0 为正数 1 为负数)。剩余的 7 个才是用来表示数字的。

已知数字 2 的二进制是 0000 0010 ,那么 -2 的二进制是多少?

根据目前已知的知识点,我最开始以为只需要把符号位的 0 改为 1 就行了,结果我又想错了。

把 2 变成 -2,有两个固定步骤

  1. 1. 2 的二进制进行取反
  2. 已知 2 的二进制是 0000 0010,取反后得到 1111 1101
  3. 2. 1
  4. 1111 1101 + 1 = 1111 1110,得出来的结果就是 -2

所以,要验证 -2 是否等于 1111 1110 ,就需要用 -2 的相反数 2 进行上面两个步骤,如果最终结果就是 1111 1110 那就说明是正确的了。(对一个负数进行上面两个步骤的操作就称为补码。之所以有补码,是为了让加法同时还可以处理减法)

3.1.3 减法计算方式

这里简单提一下在二进制的世界中是如何计算减法的。

如 5 - 3,具体思路是,先将这个减法理解为 5 + (-3),然后算出 -3 的二进制,最后将 5 的二进制和 -3 的二进制相加,就得到了最终结果。(有了补码,就可以用加法完成减法)

3.2.按位与 &

3.2.1 概念

对两个二进制进行按位与操作时,只有当前进行对比的两个位同时都是 1 时,结果才是 1。

3.2.2 示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test1 = 1;
  4. int test2 = 2;
  5. System.out.println(test1 = test1 & test2); // test1 为 0
  6. }
  7. }
  8. // 符号是 &,可以简写为 &=

步骤如下:
1.变量 test1 的值为 1,转换成二进制是 0000 0001
2.变量 test2 的值为 2,转换成二进制是 0000 0010
3.将这两个数进行按位与操作,结果是 0000 0000
4.将结果0000 0000转换成十进制就是 0

3.3.按位或 |

3.3.1 概念

对两个二进制进行按位与操作时,只要当前进行对比的两个位中有一个是 1,那么结果就是1。

3.3.2 示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test1 = 1;
  4. int test2 = 2;
  5. System.out.println(test1 = test1 | test2); // test1 为 3
  6. }
  7. }
  8. // 符号是 |,可以简写为 |=

步骤如下:
1.变量 test1 的值为 1,转换成二进制是 0000 0001
2.变量 test2 的值为 2,转换成二进制是 0000 0010
3.将这两个数进行按位或操作,结果是 0000 0011
4.将结果 0000 0011 转换成十进制就是 3

3.4.异或 ^(不进位的加法)

3.4.1 概念

对两个二进制进行异或操作,类似于加法,唯一的区别是不进位

3.4.2 示例代码

  1. public class Main {
  2. public static void main(String[] args) {
  3. int test1 = 2;
  4. int test2 = 2;
  5. System.out.println(test1 = test1 ^ test2); // 0
  6. }
  7. }
  8. // 符号是 ^,可以简写为 ^=

步骤如下:
1.变量 test1 的值为 2,转换成二进制是 0000 0010
2.变量 test2 的值为 2,转换成二进制是 0000 0010
3.将这两个数进行按位或操作,结果是 0000 0000 (按照加法处理,但是不进位 )
4.将结果 0000 0000 转换成十进制就是 0