Java——运算符

一、算数运算符

1、+(正号)

表示一个数字为正值,例如 +1 就是正一,一般可以省略,例如 1 也代表正一。

2、-(负号)

表示一个数字为负值,例如 -1 就是负一。

3、+(加号)

进行算数加运算,例如 1 + 1 = 2 。或者是变量相加。

int a = 10;
int b = 20;
int res = a + b;// res 为30

4、-(减号)

进行算数减运算,例如 1 - 1 = 0 。或者是变量相减。

int a = 10;
int b = 5;
int res = a - b;// res 为5

5、*(乘号)

进行算数乘运算,例如 2 * 2 = 4。或者是变量相乘。

int a = 2;
int b = 3;
int res = a * b;// res 为6

6、/(除号)

进行算数除运算,例如 6 / 3 = 2 。或者是变量相除。这里有一个特殊,这里的除法运算是有两种的,一种是整数除法,一种是浮点数除法

当两个操作数都是整数类型(如 intlong)时,/ 运算符执行整数除法,结果也是一个整数,任何小数部分都会被截断(即结果向零取整)。

        int a = 5;
		int b = 2;
		int res = a / b;//这里使用int变量来存储,如果不报错的话,则说明这里的a / b的结果是整型
		System.out.println(res);

这里没有报错,说明这里的 a / b 得到的就是整型数据,最终运行结果为:

这说明这里进行的是整型除法。我们都知道 5 / 2 的结果应该为 2.5 ,但这里是 2 ,就是因为这里的小数部分被截去了。

当至少有一个操作数是浮点数类型(如 floatdouble)时,/ 运算符执行浮点数除法,结果也是一个浮点数。

        double num1 = 5.0;
		int num2 = 2;
		double res = num1 / num2;
		System.out.println(res);

这里的运行结果是:

说明这里进行的是浮点数除法。

7、%(取模)

取模就是取余,也就是计算一个数除以另一个数的余数。例如 3 % 2 = 1,也就是 3 除以 2 的余数是 1 。

int a = 10;
int b = 3;
int res = a % b;// res 为1

对于取模的算法是以下的公式:

a % b = a - (int)a / b * b

也就是通过这个 a / b 是整数除法,可以得到商,然后通过使用被除数减去商与除数乘积得到余数。前面的一个 (int) 强制转换是当 a 为小数时使用的。例如:

10 % 3 = 10 - 10 / 3 * 3 = 1。

8、++(自增运算符)

使用于变量自身加一,例如 a++ 就相当于 a = a + 1 ,这会导致变量的值发生改变,正因如此,这个运算符不能对常量使用。

自增运算符以及下面的自减运算符都有一个特点,就是可以前置也可以后置,但这两种方式实现的效果不同。

1)前置++

前置++,就如 ++a ,是先将变量的值自增一,然后再使用变量。也就是先自增,再使用。例如:

    int a = 1;
	int b = ++a;//这里是先自增,后使用,所以是先 a = a + 1,然后 b = a,所以这里 b 为 2
	System.out.println("b = " + b);
	System.out.println("a = " + a);

这里是先自增,后使用,所以是先 a = a + 1,然后 b = a,这样b的值就是 2 ,a 也是自增过的,所以 a 也是2,运行结果:

2)后置++

后置++,就如 a++,是先使用变量,然后变量的值再自增一。也就是先使用,再自增。例如:

	int a = 1;
	int b = a++;//这里是先使用,再自增,所以是 b = a,然后 a = a + 1,这样b的值就是1
	System.out.println("b = " + b);
	System.out.println("a = " + a);

这里是先使用,再自增,所以是 b = a,然后 a = a + 1,这样b的值就是 1 ,然后 a 是自增一后的,所以 a 的值是2。运行结果:

9、--(自减运算符)

使用于变量自身减一,例如 a-- 就相当于 a = a - 1 ,这会导致变量的值发生改变,正因如此,这个运算符不能对常量使用。

前置 -- 和后置 -- 与前置 ++ 和后置 ++ 的情况类似。

1)前置--

前置--,就如 --a ,是先将变量的值自减一,然后再使用变量。也就是先自减,再使用。例如:

    int a = 2;
	int b = --a;//这里是先自减,后使用,所以是先 a = a - 1,然后 b = a,所以这里 b 为 1
	System.out.println("b = " + b);
	System.out.println("a = " + a);

这里是先自减,后使用,所以是先 a = a - 1,然后 b = a,所以这里 b 为 1,a 也是自减后的,所以 a 为1。运行结果:

2)后置--

后置--,就如 a--,是先使用变量,然后变量的值再自减一。也就是先使用,再自减。例如:

    int a = 2;
	int b = a--;//这里是先使用,后自减,所以是先 b = a,然后 a = a - 1,所以这里 b 为 2
	System.out.println("b = " + b);
	System.out.println("a = " + a);

这里是先使用,后自减,所以是先 b = a,然后 a = a - 1,所以这里 b 为 2,a 是自减后的,所以 a 是 1 。运行结果:

10、+(字符串连接)

小细节

后置++补充

int i = 1;
i = i++;
System.out.println(i);

运行结果:

这里是因为,对于这里的的内部实现实际上可以具象化成这样:

所以 i 是先变成了 2 ,然后又变成了 1 。

实际上对于一般的后置加加也是这样的原理,也就是会创建一个临时变量来存储原本的值,然后再自增,最后再使用临时变量中原来的值。

对于上面我们描述的先使用后递增,实际上是对于一般情况下的简化,对于上面这个特殊案例,先使用,后递增这个描述就有些错误了。

对于下面这种一般情况:

int i = 1;
a = i++;

我们就可以分析它的底层实现:

这时简化成先使用,后递增,就没有什么错误,但实际上的顺序是不对的。实际上是先递增,然后使用,只不过使用的是临时变量存储的递增之前的值。

前置++补充

对于前置++则没有上面的问题:

int i = 1;
i = ++i;

这里的步骤就像是:

所以这里与我们简化的分析是一致的,先自增,后使用。

二、关系运算符

关系运算符用于比较两个值或表达式,关系运算符的结果都是 boolean 类型的,也就是说关系运算符会返回一个布尔值(truefalse)。

关系运算符组成的表达式,我们称为关系表达式,例如 a > b 就是一个关系表达式。

关系运算符主要有以下几种:

1、==(等于)

用于比较两个操作数是否相等。如果相等,则返回true,否则返回false

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 30;
		System.out.println(a + " == " + b + " is " + (a == b));
	}
}

运行结果:

2、!=(不等于)

用于比较两个操作数是否不相等。如果不相等,则返回true,否则返回false

    int a = 10;
	int b = 30;
	System.out.println(a + " != " + b + " is " + (a != b));

运行结果

3、>(大于)

用于判断左操作数是否大于右操作数。如果是,则返回true,否则返回false

    int a = 10;
	int b = 30;
	System.out.println(a + " > " + b + " is " + (a > b));

运行结果:

4、<(小于)

用于判断左操作数是否小于右操作数。如果是,则返回true,否则返回false

    int a = 10;
	int b = 30;
	System.out.println(a + " < " + b + " is " + (a < b));

运行结果:

5、>=(大于或等于)

用于判断左操作数是否大于或等于右操作数。如果是,则返回true,否则返回false

    int a = 10;
	int b = 30;
	System.out.println(a + " >= " + b + " is " + (a >= b));

运行结果:

6、<=(小于或等于)

用于判断左操作数是否小于或等于右操作数。如果是,则返回true,否则返回false

    int a = 10;
	int b = 30;
	System.out.println(a + " <= " + b + " is " + (a <= b));

运行结果:

三、逻辑运算符

逻辑运算符用于布尔值之间的操作,并返回布尔结果(truefalse)。逻辑运算符主要有以下几种:

1、&(逻辑与)

这里的 & 在逻辑运算符中的话就是逻辑与运算符,在二进制运算符中,就是按位与运算符。这取决于它的操作数的类型:

  • 当操作数是布尔类型时,& 执行逻辑与操作。只有当两个操作数都为true时,结果才为true
  • 当操作数是数值类型时,& 执行按位与操作。它对两个操作数的每一位执行与操作。

在这里我们介绍的是它作为逻辑与运算符,它的运算规则是:

a & b :当ab同时为true时,结果为true,否则为false。(这里的 a 和 b 可以是 boolean 类型的变量,也可以是结果为 boolean 类型值的表达式,以下的逻辑表达式中的 a 与 b 也是此情形)

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		boolean b = true;
		System.out.println("a & b = " + (a & b));
	}
}

运行结果:

&(逻辑与)与下面的短路与不同的是,逻辑与在 a 为 false 时,仍会计算后面的 b,我们下面使用一个例子演示一下:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		if(a < 2 & b++ > 10) {//这里是逻辑与,对于前面的表达式a < 2明显为假,
							   //但是它仍旧会运算后面的表达式,
							   //所以b++会运算,所以b会自增,
							   //所以b变成了21
			System.out.println("Hello");
		}
		System.out.println("a = " + a + "\nb = " + b);
	}
}

运行结果:

这里是逻辑与,对于前面的表达式a < 2明显为假,但是它仍旧会运算后面的表达式,所以b++会运算,所以b会自增,所以b变成了21。

2、&&(短路与)

a && b :当ab同时为true时,结果为true,否则为false。如果afalse,则不会计算b(短路特性)。

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		boolean b = true;
		System.out.println("a && b = " + (a && b));
	}
}

运行结果:

短路与和上面的逻辑与的唯一区别就是如果 a 为 false,则不会再计算 b。因为对于逻辑中的与操作,只要有一个表达式为 false,那么就可以确定整个表达式为 false 了。我们可以通过下面的一个例子进行测试这个特性:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		if(a < 2 && b++ > 10) {//这里是短路与,对于前面的表达式a < 2明显为假,
							   //所以后面的表达式不会运算所以b++也不会运算,所以b不会自增,
							   //所以b还是20
			System.out.println("Hello");
		}
		System.out.println("a = " + a + "\nb = " + b);
	}
}

运行结果:

由于这里是短路与,而且对于前面的表达式a < 2明显为假,所以后面的表达式不会运算所以b++也不会运算,所以b不会自增,所以b还是20

开发中我们一般使用 &&(短路与),因为它可以节省性能,效率较高。

3、|(逻辑或)

逻辑或运算符的处境与逻辑与的处境相似:| 在逻辑运算符中的话就是逻辑或运算符,在二进制运算符中,就是按位或运算符。这取决于它的操作数的类型:

  • 当操作数是布尔类型时,| 执行逻辑或操作。只要有一个操作数为true,结果就为true
  • 当操作数是整数类型时,| 执行按位或操作。它对两个操作数的每一位执行或操作。

在这里我们介绍的是它作为逻辑或运算符,它的运算规则是:

a | b :当ab有一个为true时,结果为true,否则为false

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		boolean b = false;
		System.out.println("a | b = " + (a | b));
	}
}

运行结果:

|(逻辑或)与下面的短路或不同的是,逻辑或在 a 为 true 时,仍会计算后面的 b,我们下面使用一个例子演示一下:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		if(a > 0 | b++ > 10) {//这里是逻辑或,对于前面的表达式a > 0明显为真,
							   //但是它仍旧会计算后面的表达式,
							   //所以b++也会运算,所以b就会自增,
							   //所以b就变为了21
			System.out.println("Hello");//而且因为这里的总表达式为真,所以会打印Hello
		}
		System.out.println("a = " + a + "\nb = " + b);
	}
}

运行结果:

这里是逻辑或,对于前面的表达式a > 0明显为真,但是它仍旧会计算后面的表达式,所以b++也会运算,所以b就会自增,所以b就变为了21

4、||(短路或)

a || b :当ab有一个为true时,结果为true,否则为false。如果atrue,则不会计算b(短路特性)。

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		boolean b = false;
		System.out.println("a || b = " + (a || b));
	}
}

运行结果:

短路或和上面的逻辑或的唯一区别就是如果 a 为 true,则不会再计算 b。因为对于逻辑中的或操作,只要有一个表达式为 true,那么就可以确定整个表达式为 true 了。我们可以通过下面的一个例子进行测试这个特性:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		if(a > 0 || b++ > 10) {//这里是短路或,对于前面的表达式a > 0明显为真,
							   //所以后面的表达式不会运算,
							   //所以b++不会运算,所以b不会自增,
							   //所以b还是20
			System.out.println("Hello");//而且因为这里的总表达式为真,所以会打印Hello
		}
		System.out.println("a = " + a + "\nb = " + b);
	}
}

运行结果:

这里是短路或,对于前面的表达式a > 0明显为真,所以后面的表达式不会运算,所以b++不会运算,所以b不会自增,所以b还是20

开发中我们一般使用 ||(短路或),因为它可以节省性能,效率较高。

5、!(逻辑非)

!a :取a的反值。如果atrue,结果为false;如果afalse,结果为true

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		System.out.println("!a = " + (!a));
	}
}

运行结果:

6、^(逻辑异或)

在逻辑运算符中的话就是逻辑或异或算符,在二进制运算符中,就是按位异或运算符。这取决于它的操作数的类型:

  • 当操作数是布尔类型时,^ 执行逻辑或操作。只要一个操作数为true,另一操作数是false,结果为true,否则为false。也就是相同为false,相异为true
  • 当操作数是整数类型时,^ 执行按位或操作。它对两个操作数的每一位执行或操作。

在这里我们介绍的是它作为逻辑异或运算符,它的运算规则是:

如果两个布尔操作数不同(即一个为true,另一个为false),结果为true;如果两个操作数相同,结果为false

public class Test {
	public static void main(String[] args) {
		boolean a = true;
		boolean b = true;
		System.out.println("a ^ b = " + (a ^ b));
	}
}

运行结果:

四、位运算符

位运算符都是在二进制补码的基础上进行操作的。

1、&(按位与)

1)介绍

对两个操作数的对应位执行与操作。仅当对应位均为1时,结果位才为1,否则为0。

假设某两个数的二进制补码某同一位上的数字为 p 和 q :

pqp & q
111
010
100
000

例如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int b = 5;
		int res = a & b;
		System.out.println("-7 & 5 = " + res);
	}
}

运行结果:

下面进行具体分析:

最终结果为 1 ,与运行结果一致。

2)特点

任何数按位与 0 的结果都是 0 ,任何数按位与其本身的结果都是其本身。

2、|(按位或)

1)介绍

对两个操作数的对应位执行或操作。只要对应位有一个为1,结果位就为1,否则为0。

假设某两个数的二进制补码某同一位上的数字为 p 和 q :

pqp | q
111
101
011
000

例如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int b = 5;
		int res = a | b;
		System.out.println("-7 | 5 = " + res);
	}
}

运行结果:

下面进行详细分析:

上面已经求出 -7 的补码,这里不再赘述。

与运行结果一致。

2)特点

任何数按位或 0 结果都是这个数本身。

3、^(按位异或)

1)介绍

对两个操作数的对应位执行异或操作。当对应位不同(一个为1,一个为0)时,结果位为1,否则为0。

假设某两个数的二进制补码某同一位上的数字为 p 和 q :

pqp ^ q
110
101
011
000

例如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int b = 5;
		int res = a ^ b;
		System.out.println("-7 ^ 5 = " + res);
	}
}

运行结果:

2)特点

任何数按位异或自身的结果都是 0 ,任何数按位异或 0 都是其本身。

按位异或运算满足交换律:

a ^ b ^ c = a ^ c ^ b = b ^ c ^ a = b ^ a ^ c = c ^ a ^ b = c ^ b ^ a

例如:

public class Test {
	public static void main(String[] args) {
		int a = 1 ^ 2 ^ 3;
		int b = 1 ^ 3 ^ 2;
		int c = 2 ^ 1 ^ 3;
		int d = 2 ^ 3 ^ 1;
		int e = 3 ^ 1 ^ 2;
		int f = 3 ^ 2 ^ 1;
		System.out.println("1 ^ 2 ^ 3 = " + a);
		System.out.println("1 ^ 3 ^ 2 = " + a);
		System.out.println("2 ^ 1 ^ 3 = " + a);
		System.out.println("2 ^ 3 ^ 1 = " + a);
		System.out.println("3 ^ 1 ^ 2 = " + a);
		System.out.println("3 ^ 2 ^ 1 = " + a);
	}
}

运行结果:

一个很神奇的题目做法:

不使用临时变量,交换两个变量的值。

public class Test {
	public static void main(String[] args) {
		int a = 3;
		int b = 5;
		System.out.println("交换前");
		System.out.println("a = " + a + "\nb = " + b);
		a = a ^ b;
		b = a ^ b;
		a = a ^ b;
		System.out.println("交换后");
		System.out.println("a = " + a + "\nb = " + b);
	}
}

运行结果:

核心代码就是:

	a = a ^ b;
	b = a ^ b;
	a = a ^ b;

下面进行详细介绍:

4、~(按位取反)

1)介绍

对操作数的每个位(包括符号位)执行取反操作,即0变1,1变0。

假设某一个数的二进制补码某一位上的数字为 p  :

p~p
10
01

例如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int res = ~a;
		System.out.println("~a = " + res);
	}
}

运行结果:

下面进行详细介绍:

与运行结果一致。

2)特点

我们可以直接对一个数使用取反加一来求一个数字的相反数:

		int a = 2;
		int b = ~a + 1;

		System.out.println(a);
		System.out.println(b);

运行结果:

我们可以看一下图解:

具体原因可以看我之前的文章《Java——二进制原码、反码和补码_原码反码补码-CSDN博客》。

5、<<(左移)

1)介绍

将操作数的所有位向左移动指定的位数,右边补0。左移n位相当于乘以2的n次方。

例如:

public class Test {
	public static void main(String[] args) {
		int a = 5;
		int res = a << 2;//左移两位
		System.out.println("a << 2 = " + res);
	}
}

运行结果:

下面进行详细介绍:

左移 2 位就相当于乘以 2 的 2 次方,也就是乘以 4 ,5 乘以 4 为 20,与我们运行结果和分析是一致的。

又如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int res = a << 2;//左移两位
		System.out.println("-7 << 2 = " + res);
	}
}

运行结果:

下面进行详细分析:

左移 2 位相当于乘 2 的 2 次方,也就是乘 4 ,-7 乘 4 为 -28 。最终结果为 -28,与运行结果一致。

2)特别补充

左移是会连带符号位一起移动的,也就是说无论是数值位还是符号位,都要左移。

我们可以通过下面的例子进行验证:

public class Test {
	public static void main(String[] args) {
		int a = -2147483647;
		//11111111 11111111 11111111 11111111    -2147483647 的原码
		//10000000 00000000 00000000 00000001    -2147483647 的补码

		//假设 1、不移符号位 10000000 00000000 00000000 00000010补码
		//            11111111 11111111 11111111 11111110原码
		//            结果为 -2147483646

		//假设 2、移动符号位 00000000 00000000 00000000 00000010
		//            结果为 2
		System.out.println("结果为 " + (a << 1));
	}
}

最终运行结果为:

所以说实际情况是我们的假设 2 的情况,也就是左移时符号位也会左移

6、>>(算数右移)

将操作数的所有位向右移动指定的位数,左边补符号位(即正数补0,负数补1)。右移n位相当于除以2的n次方(向下取整,就是取整较小的数)。

例如:

public class Test {
	public static void main(String[] args) {
		int a = 5;
		int res = a >> 2;//算数右移两位
		System.out.println("5 >> 2 = " + res);
	}
}

运行结果:

下面进行详细分析:

算数右移 2 位相当于除以 2 的 2 次方,也就是除以 4 ,5 除以 4 为 1.25 ,向下取整,取较小的数,为 1,所以结果为 1,与运行结果一致。

又如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int res = a >> 2;//算数右移两位
		System.out.println("-7 >> 2 = " + res);
	}
}

运行结果:

下面进行详细分析:

算数右移 2 位相当于除以 2 的 2 次方,也就是除以 4 ,-7 除以 4 为 -1.75 ,向下取整,取较小的数,为 -2( -2 小于 -1 ),所以结果为 -2,与运行结果一致。

7、>>>(逻辑右移 / 无符号右移)

将操作数的所有位向右移动指定的位数,左边补 0。逻辑右移忽略符号位,对正负数都用 0 填充左边空位。

例如:

public class Test {
	public static void main(String[] args) {
		int a = 5;
		int res = a >>> 2;//逻辑右移两位
		System.out.println("5 >>> 2 = " + res);
	}
}

运行结果:

这里的分析与运行结果一致。对于正数算数右移和逻辑右移的结果是一样的,因为在算数右移中,正数的左边也是补0,在逻辑右移中,正数的右边同样是补0。

又如:

public class Test {
	public static void main(String[] args) {
		int a = -7;
		int res = a >>> 2;//逻辑右移两位
		System.out.println("-7 >>> 2 = " + res);
	}
}

运行结果:

下面进行详细分析:

最终结果与运行结果一致。

五、赋值运算符

在Java中,赋值运算符左侧必须是左值(L-value),右侧可以是右值(R-value)或左值。

左值(L-value,Left Value 或 Locator Value)

  • 左值是指可以出现在赋值操作符左边的表达式。它表示一个存储位置,可以被赋值。
  • 左值是可以被取地址的(即它们有存储位置)。
  • 在Java中,左值通常是变量或对象属性。
int x = 10; // x 是左值,可以被赋值

右值(R-value,Right Value 或 Read value)

  • 右值是指出现在赋值操作符右边的表达式。它表示一个数据值,可以被读取。
  • 右值不一定要有存储位置,可以是常量、字面值或者表达式的结果。
  • 右值可以是变量的值。
int y = x; // x 是左值,但在这里作为右值使用,表示 x 的值
int z = 5; // 5 是右值

1、=(简单赋值运算符)

用于将右侧的值赋给左侧的变量。

int a = 5; // 将值 5 赋给变量 a

2、+=(加法赋值运算符)

将右侧的值加到左侧变量的当前值,并将结果赋给左侧变量。

int a = 5;
a += 3; // 等同于 a = a + 3,结果 a 为 8

3、-=(减法赋值运算符)

将右侧的值从左侧变量的当前值中减去,并将结果赋给左侧变量。

int a = 5;
a -= 3; // 等同于 a = a - 3,结果 a 为 2

4、*=(乘法赋值运算符)

将左侧变量的当前值与右侧的值相乘,并将结果赋给左侧变量。

int a = 5;
a *= 3; // 等同于 a = a * 3,结果 a 为 15

5、/=(除法赋值运算符)

将左侧变量的当前值除以右侧的值,并将结果赋给左侧变量。

int a = 6;
a /= 3; // 等同于 a = a / 3,结果 a 为 2

6、%=(取模赋值运算符)

将左侧变量的当前值与右侧的值取模运算,并将结果赋给左侧变量。

int a = 5;
a %= 3; // 等同于 a = a % 3,结果 a 为 2

7、&=(按位与赋值运算符)

将左侧变量的当前值与右侧的值按位与运算,并将结果赋给左侧变量。

int a = 5; // 二进制补码:00000000 00000000 00000000 00000101
int b = 3; // 二进制补码:00000000 00000000 00000000 00000011
a &= b; // 等同于 a = a & b,结果 a 为 1(二进制补码:00000000 00000000 00000000 00000001)

8、|=(按位或赋值运算符)

将左侧变量的当前值与右侧的值按位或运算,并将结果赋给左侧变量。

int a = 5; // 二进制补码:00000000 00000000 00000000 00000101
int b = 3; // 二进制补码:00000000 00000000 00000000 00000011
a |= b; // 等同于 a = a | b,结果 a 为 7(二进制:00000000 00000000 00000000 00000111)

9、^=(按位异或赋值运算符)

将左侧变量的当前值与右侧的值按位异或运算,并将结果赋给左侧变量。

int a = 5; // 二进制:00000000 00000000 00000000 00000101
int b = 3; // 二进制:00000000 00000000 00000000 00000011
a ^= b; // 等同于 a = a ^ b,结果 a 为 6(二进制:00000000 00000000 00000000 00000110)

10、<<=(左移赋值运算符)

将左侧变量的当前值左移指定的位数,并将结果赋给左侧变量。

int a = 5; // 二进制:0101
a <<= 1; // 等同于 a = a << 1,结果 a 为 10(二进制:1010)

11、>>=(算数右移赋值运算符)

将左侧变量的当前值算数右移(右移时左侧用符号位填充)指定的位数,并将结果赋给左侧变量。

int a = 5; // 二进制:0101
a >>= 1; // 等同于 a = a >> 1,结果 a 为 2(二进制:0010)

12、>>>=(逻辑右移赋值运算符)

将左侧变量的当前值无符号逻辑右移(右移时左侧用零填充)指定的位数,并将结果赋给左侧变量。

int a = -5; // 二进制:11111111111111111111111111111011
a >>>= 1; // 等同于 a = a >>> 1,结果 a 为 2147483645(二进制:01111111111111111111111111111101)

补充:

复合赋值运算符会自动进行类型转换。

就如:

byte num1 = 1;
num1 += 2;

我们说这里的 num1 += 2;相当于 num1 = num1 + 2;但是如果是真的相当于这里的:

num1 = num1 + 2;

那这里的 num1 的类型是 byte ,它在计算时会提升至 int 类型,这里后面的部分 num1 + 2 得到的结果应当是 int 类型,如果直接赋值给一个 byte 类型的变量,理应会报错,但这里没有,就是因为这里的复合赋值运算符不仅仅是等价于这个语句,而且复合赋值运算符还会自动进行类型转换,它实际上应当相当于:

num1 = (byte)(num1 + 2);

实际上对于我们之前说的 i++ 相当于 i = i + 1 与这里是相似的,它应当相当于:

i = (type)(i + 1);

六、其他运算符

1、? :(三元运算符 / 条件运算符)

介绍:

用于基于一个布尔表达式的结果选择值。这个运算符是一种简洁的if-else表达形式,可以大大简化代码,提高可读性。三元运算符的语法如下:

conditionExpression ? expression1 : expression2;

conditionExpression 是条件表达式,当条件表达式的结果为 true 时,expression1 的值就是这个三元表达式的值,当表达式的结果为 false 时,expression2 的值就是这个三元表达式的值。

  • conditionExpression 是一个布尔表达式。
  • expression1 是当 conditionExpression 为 true 时的结果。
  • expression2 是当 conditionExpression 为 false 时的结果。
public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int max = (a > b) ? a : b;//利用三元运算符求两个数的最大值
		System.out.println("The maximum number between " + a + " and " + b + " is " + max);
	}
}

运行结果:

补充:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int result = (a > b) ? a++ : b++;
		System.out.println("a = " + a + "\nb = " + b + "\nresult = " + result);
	}
}

运行结果:

这里的 a > b 为 false ,所以执行表达式二,即 b++ ,这时因为是后置++,所以会先使用,后自增,所以这里的 result 被赋值为 20 ,然后 b 自增,b 就变成了 21 。这里的表达式一,即 a++ ,并没有执行,所以 a 没有自增,所以 a 还是 10。

三元运算符可以嵌套:

public class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int c = 30;
		int max = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
		//利用嵌套三元运算符实现求三个数的最大值
		System.out.println(max);
	}
}

运行结果:

2、instanceof 运算符

instanceof 运算符是Java中用于测试对象是否是某个特定类或其子类的实例的关键字。它在运行时进行类型检查,返回一个布尔值(truefalse),用于确保对象的类型安全性。instanceof 运算符的基本语法如下:

object instanceof ClassName;
  • object 是需要进行类型检查的对象。
  • ClassName 是你希望检查的类或接口。

示例:

public class Test {
	public static void main(String[] args) {
		boolean res = "Hello" instanceof String;
		System.out.println(res);
	}
}

运行结果:

字符串 "Hello" 实际上是 String 类的一个对象,因此 instanceof 运算符会返回 true

"Hello" 是一个 String 对象。instanceof 运算符用于检查 "Hello" 是否是 String 类的一个实例。由于 "Hello" 确实是 String 类的一个实例,所以 res 的值为 trueSystem.out.println(res) 将输出 true

运算符的优先级

运算符有不同的优先级,优先级就是表达式中的运算顺序。就像我们在计算 1 + 2 * 3 时总是要先算乘法一样,在这个表达式中,乘法的优先级较高。

类别操作符关联性
后缀() [] . (点操作符)从左到右
一元expr++ expr--从左到右
一元++expr --expr + - ~ !从右到左
乘性 * /%从左到右
加性 + -从左到右
移位 >> >>>  << 从左到右
关系 > >= < <= instanceof从左到右
相等 ==  !=从左到右
按位与从左到右
按位异或^从左到右
按位或|从左到右
逻辑与&&从左到右
逻辑或| |从左到右
条件?:从右到左
赋值= + = - = * = / =%= >> = << =&= ^ = | =从右到左
逗号从左到右
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值