Java基础教程 - 3 运算符

发布于:2024-05-01 ⋅ 阅读:(34) ⋅ 点赞:(0)

更好的阅读体验:点这里www.doubibiji.com

3 运算符

在编写有逻辑的代码前,先学习一下 Java 中的运算符。

下面介绍 Java 中常见的运算符:算数运算符赋值运算符关系运算符


3.1 算数运算符

算数运算符是干嘛的?

就是进行数学运算的,就是小学学的加、减、乘、除等。

Java 中常见的算数运算符如下:

运算符 描述 示例
+ 加法 a + b
- 减法 a - b
* 乘法 a * b
/ 除法 a / b
% 取余,模运算 a % b

举个例子:

public class HelloJava {
    public static void main(String[] args) {
        int a = 10;
        int b = 3;

        System.out.println(a + b); 		// 输出 13
        System.out.println(a - b); 		// 输出 7
        System.out.println(a * b); 		// 输出 30
        System.out.println(a / b); 		// 输出 3
        System.out.println(a % b); 		// 输出 1
    }
}

注意:两个整数相除,结果还是整数,小数部分会被去掉。

如果想让两个整数相除,保留小数部分,可以先乘上1.0,举个栗子:

int a = 10;
int b = 3;

System.out.println(1.0 * a / b); 		// 输出 3.3333333333333335

加减乘除在运算中用的是最多的,但是模运算有时候也会用到,下面举个栗子:

求1789的十位数是多少?

int i = 1789;
int j = i / 10 % 10;
System.out.println(j);  // 结果为:8

因为 i 是整形的,所以 i / 10 只会保留整数部分,得到 178178 % 10,余数是 8

同样,如果判断一个整数是否是偶数,那么可以将这个数 % 2,然后查看结果是否是 0,如果是 0 就是偶数,否则是奇数。


算数运算符也是有优先级的,和在小学的时候学习的一样。

int i = 3 + 2 * 4;
System.out.println(i);  // 结果为:11

乘、除、取模运算的优先级大于加、减运算

3.2 赋值运算符

赋值运算符就是用来给变量赋值的。

赋值运算符
运算符 描述 举例
= 赋值运算符 就是把 = 右边的值赋值给左边的变量,之前用过了。

例如:

int a = 2;
int b = 3;
int c = a + b;

除了赋值运算符,下面还有复合赋值运算符。

复合赋值运算符

复合赋值运算符就是经过计算后,将值赋给前面的变量。

Java 中常用的复合赋值运算符如下:

运算符 描述 举例
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
~/= 整除赋值运算符 c ~/= a 等效于 c = c ~/ a

举个栗子:

public static void main(String[] args) {
    int a = 5;
    int b = 3;
    a += b; // a = a + b
    System.out.println(a); // 8

    a = 5;
    a -= b; // a = a - b
    System.out.println(a); // 2

    a = 5;
    a *= b; // a = a * b
    System.out.println(a); // 15
}

复合赋值运算符感觉这么写可读性还变差了,有什么好处呢?

  1. 更加简练;
  2. 避免类型转换的麻烦;

是如何避免类型转换的,举个栗子:

short s = 10;
// s = s + 2;							// 编译失败,因为得到的结果是int类型,无法赋值给short
s += 2;	    							// 可以,复合赋值运算符不会改变变量本身的数据类型
System.out.println(s);    // 12

复合赋值运算符运算完成,类型是不变的,如果使用普通方式,则需要强制转换 s = (short)(s + 2)

3.3 自增自减运算符

Java中的自增自减运算符包括++--。它们可以用于对变量进行加1或减1操作。

举个栗子:

public static void main(String[] args) {
    int a = 5;
    a++; // a自增1
    System.out.println(a); // 输出 6
    a--; // a自减1
    System.out.println(a); // 输出 5
}

需要注意的是,自增自减运算符可以放在变量的前面或后面,这会影响到表达式的值。

如果运算符放在变量的前面,表示先加减,后使用;如果运算符放在变量的后面,表示先试用,后加减。

举个栗子:

public static void main(String[] args) {
    int a = 5;
    int b = a++; 		// 先使用a的值还是5,后加减,a加1,a值为0
    System.out.println(b); 			// 5
    System.out.println(a); 			// 6

    int c = 5;
    int d = ++c; 		// 先加减c+1变为6,后使用,d的值为6
    System.out.println(d); 			// 6
    System.out.println(c); 			// 6
}

-- 操作符也是一样的。

++-- 运算符也不会改变变量的数据类型,举个栗子:

short s = 10;
short t = s ++;         // 仍然是short类型
System.out.println(t);  // 11

3.4 关系运算符

关系运算符也就是比较运算符,主要有以下几种:

运算符 > < >= <= == !=
含义 大于 小于 大于等于 小于等于 等于 不等于

举个栗子:

public static void main(String[] args) {
    int a = 10;
    int b = 3;
    boolean c = a == b;     // 将比较运算的结果赋值给c
    System.out.println(c);          // false
  
    boolean d = a > b;     // 将比较运算的结果赋值给c
    System.out.println(d);          // true

    System.out.println(a != b);     // true
    System.out.println(a < b);      // false
    System.out.println(a >= b);     // true
    System.out.println(a <= b);     // false

    String str1 = "Doubi";
    String str2 = "Doubi";
    System.out.println(str1.equals(str2));	// true
}

关系运算符得到的结果都是 boolean 类型,在后面可以通过使用关系运算符来进行条件的判断。例如身高大于120cm就要买儿童票等场景。

这里需要注意,如果比较两个字符串是否相等,不要使用 == 运算符,要使用 equals() 方法。

因为字符串是引用类型,对于引用类型,== 运算符比较的是两个变量内存地址是否相同,而不是比较对象的内容。

3.5 逻辑运算符

1 逻辑运算符

主要有以下三种:

运算符 && || !
含义 与,两边条件同时满足 或,两边条件满足一个即可 非,取反值,真为假,假为真

举个栗子:

public static void main(String[] args) {
    boolean a = true;
    boolean b = false;
    System.out.println(a && b); 		// false
    System.out.println(a || b); 		// true
    System.out.println(!a); 			  // false
}

逻辑运算符两边必须是 boolean 类型的变量或结果为 boolean 类型的表达式。

逻辑运算符得到的结果还是 boolean 类型,可以赋值给 boolean 类型的变量。

再举个例子:

public static void main(String[] args) {
    int a = 3;
    int b = 12;

    System.out.println(a > 5 && b > 10); 		// false
    System.out.println(a > 5 || b > 10); 		// true
    System.out.println(!(a > 5));           // true
}

!(a > 5) 是将 a > 5 的结果取反。 a > 5 结果为 false ,取反则为 true

2 逻辑运算符的优先级

优先级:! > && > ||

举个栗子:

public static void main(String[] args) {
    int a = 3;
    int b = 12;
    int c = 6;
    int d = 10;
    System.out.println(a > 5 && b > 10 || c > 5 && d > 10);      // false
}

当一个逻辑运算语句中同时包含与、或 、 非运算的时候,会按照优先级进行运算。

所以上面先运算 a > 5 && b > 10,然后运算 c > 5 && d > 10,最后运算 || 两边的结果。


再举个例子:

public static void main(String[] args) {
    boolean a = true;
    boolean b = false;

    boolean result = !a || a && b;
    System.out.println(result);         // false
}

先运算 !a ,结果为 false,然后运算 a && b,结果为 false,最后运算 || 两边的结果,为 false

如果搞不清楚先后运算的顺序,就用括号 () 括起来,准没错。

3 逻辑短路

逻辑短路就是在进行逻辑运算的时候,如果已经能够得到最后的值,就不会再继续进行判断了。

只有 与运算符 && 和 或运算符 || 存在逻辑短路。

举个栗子:

public static void main(String[] args) {
    int num = 10;
    boolean b = num > 20 && num++ < 40;
    System.out.println(num);			 // 10
}

在执行上面代码的时候,num > 20 已经不成立了,而 && 运算需要两边都满足,所以后面的条件成不成立都不会影响最终逻辑表达式的结果,所以 && 后面的 num++ < 40 就不会再继续执行了,那么 num 的值就没有 ++,这就是逻辑短路。


同样 || 运算符:

public static void main(String[] args) {
    int num = 10;
    boolean b = num < 20 || num++ > 40;
    System.out.println(num);			// 10
}

在执行上面代码的时候,num < 20 已经成立了,|| 运算只要一边满足即可,所以整个逻辑表达式肯定是成立的,所以 || 后面的 num++ > 40 就不会继续执行了,那么 num 的值就没有 ++


如果不想逻辑短路,可以使用 &| 运算符,一个&| 时,左边无论真假,右边都进行运算。

以逻辑与,修改上面的代码:

public static void main(String[] args) {
    int num = 10;
    boolean b = num > 20 & num++ < 40;
    System.out.println(num);        // 11
}

使用 & 运算符,就不存在逻辑短路问题,无论左边的运算结果为 truefalse,右边都会执行运算。

&| 运算符用的不多,开发中主要使用 &&||

3.6 位运算符

位运算符在实际的开发中用的不多,在底层代码中会用到,这里了解一下即可。

位运算符允许你直接操作数据的二进制表示形式的各个位。这些运算符可以用于执行各种位级操作,如按位与、按位或、按位取反和按位移动等。位运算符都是对整数类型(如int、long等)进行操作。

建议先学习一下本站的 计算机基础知识 教程。


1.左移(<<)

  • 符号: <<
  • 作用: 将操作数的所有位向左移动指定的位数,包括符号位,右侧空出的位用0填充。

举个栗子:

public static void main(String[] args) {
    int i = 1;
    int j = i << 2;
    System.out.println(j);  // 4
}

1 的 int 类型,4个字节存储,二进制表示为00000000 00000000 00000000 00000001 ,左移两位,变为 00000000 00000000 00000000 00000100,即为4,左移后,右侧补0。

所以左移n位时候,相当于乘上 2^n 次幂。

  1. 右移(>>)
  • 符号: >>
  • 作用: 将操作数的所有位向右移动指定的位数,左侧空出的位使用符号位(正数用0填充,负数用1填充)进行填充。

举个栗子:

public static void main(String[] args) {
    int i = -7;
    int j = i >> 2;
    System.out.println(j);  // -2
}

-7 的二进制表示是 11111111 11111111 11111111 11111001,右移两位,右侧被移除两位,变为 11111111 11111111 11111111 11111110,也就是 -2

  1. 无符号右移(>>>)
  • 作用: 将操作数的所有位向右移动指定的位数(包括符号位),左侧空出的位使用0填充。

举个栗子:

public static void main(String[] args) {
    int i = -7;
    int j = i >>> 2;
    System.out.println(j);  // 1073741822
}

-7 的二进制表示是 11111111 11111111 11111111 11111001,右移两位,包括符号位,右侧被移除两位,变为 00111111 11111111 11111111 11111110,也就是 1073741822

注意:是没有 <<< 运算符的。

  1. 按位与(&)
  • 符号:&
  • 作用: 对两个操作数的每一个位执行逻辑与操作,只有两个位都为1时结果才为1,否则为0。

举个栗子:

public static void main(String[] args) {
    int a = 15; // 二进制表示为 1111
    int b = 9;  // 二进制表示为 1001

    // 按位与
    int resultAnd = a & b; // 结果为 9 (0000 1001)
    System.out.println("按位与结果:" + resultAnd);
}

每一位进行操作,并得到结果:

  00000000 00000000 00000000 00001111
& 00000000 00000000 00000000 00001001
= 00000000 00000000 00000000 00001001 = 9
  1. 按位或(|)
  • 符号:|
  • 作用: 对两个操作数的每一个位执行逻辑或操作,只要两个位中有一个为1,结果就为1。

举个栗子:

public static void main(String[] args) {
    int a = 15; // 二进制表示为 1111
    int b = 9;  // 二进制表示为 1001

    // 按位或
    int resultOr = a | b; // 结果为 15 (0000 1111)
    System.out.println("按位或结果:" + resultOr);
}

每一位进行操作,并得到结果:

  00000000 00000000 00000000 00001111
| 00000000 00000000 00000000 00001001
= 00000000 00000000 00000000 00001111 = 15
  1. 按位异或(^)
  • 符号:^
  • 作用: 对两个操作数的每一个位执行异或操作,两个位相同则结果为0,不同则结果为1。

举个栗子:

public static void main(String[] args) {
    int a = 15; // 二进制表示为 1111
    int b = 9;  // 二进制表示为 1001

    // 按位异或
    int resultXor = a ^ b; // 结果为 6 (0000 0110)
    System.out.println("按位异或结果:" + resultXor);
}

每一位进行异或操作,并得到结果:

  00000000 00000000 00000000 00001111
| 00000000 00000000 00000000 00001001
= 00000000 00000000 00000000 00000110 = 6
  1. 按位取反(~)
  • 符号:~
  • 作用: 对操作数的每一个位执行取反操作(包括符号位),将每个1变为0,每个0变为1。

举个栗子:

public static void main(String[] args) {
    int a = 15; // 二进制表示为 1111
    
    // 按位取反
    int resultNotA = ~a; // 结果为 -16 (1111 0000)
    System.out.println("按位取反结果:" + resultNotA);
}

每一位进行取反操作,并得到结果:

   00000000 00000000 00000000 00001111
~= 11111111 11111111 11111111 11110000 = -16

上面的运算了解一下就好了,实际开发中不涉及底层的,基本用不到。

3.7 运算符优先级

上面那么多运算符,如果同时运算的时候,优先级是怎么样的呢?

举个栗子:

public static void main(String[] args) {
    int a = 5;
    int b = 10;
    int c = 15;
    int d = 5;
    int e = 25;
    int f = 2;
    int g = 3;
    int h = 40;
    int i = 1;
    int j = 2;
    boolean m = a + b * c / d - e << f >>> g > 0 && h >> i * j > 0;
    System.out.println(m);
}

看着上面的代码,眼不眼晕。在实际的开发中,不要这样写,可读性太差了。


在 Java 中运算符的优先级,按照高到低的顺序如下:

优先级 运算符 分类
1 ++ , -- 递增/递减
2 * , / , % 乘法、除法和取模
3 + , - 加法和减法
4 << , >> , >>> 位移运算
5 < , <= , > , >= 比较运算
6 == , != 相等和不等运算
7 & 按位与
8 ^ 按位异或
9 ` `
10 && 逻辑与
11 `
12 ?: 条件运算符,后面讲解
13 = , += , -= , *= , /= , %= 赋值运算符

所以上面的代码,根据优先级括号,应该是这样的:

boolean m = (((a + (b * c / d) - e) << f) >>> g) > 0 && (h >> (i * j)) > 0;

在开发中,不知道优先级高低,添加括号就可以了。


网站公告

今日签到

点亮在社区的每一天
去签到