运算符和表达式是编写代码时进行数据计算和逻辑操作的基础。
运算符
定义了如何处理变量和值之间的数学和逻辑操作。表达式
则是由变量、常量和运算符组成的代码片段,它们可以计算出一个值。
算术运算符
算术运算符用于执行基本的数学运算,包括加法、减法、乘法、除法和取模。这些运算符可以作用于整数和浮点数类型的数据,用于计算结果或对变量进行更新。
- 加法运算符(
+
)- 用于两个数值的相加。
- 可以用于连接字符串。
int a = 10;
int b = 3;
double c = 4.5;
double d = 2.5;
// 加法运算
int sum = a + b;
System.out.println(a + " + " + b + " = " + sum);
double sum2 = c + d;
System.out.println(c + " + " + d + " = " + sum2);
// 字符串拼接
System.out.println(a + " + " + b + " = " + (a+b));
- 减法运算符(
-
)- 用于两个数值的相减。
- 也可以用于获取一个数的相反数(例如,
-x
)。
int sum3 = a - b;
System.out.println(a + " - " + b + " = " + sum3);
double sum4 = c - d;
System.out.println(c + " - " + d + " = " + sum4);
- 乘法运算符(
*
)- 用于两个数值的相乘。
int sum5 = a * b;
System.out.println(a + " * " + b + " = " + sum5);
double sum6 = c * d;
System.out.println(c + " * " + d + " = " + sum6);
- 除法运算符(
/
)- 用于两个数值的相除。
- 当操作数为整数时,结果为整数除法,小数部分会被丢弃。
- 浮点数不建议进行除法运算
int sum7 = a / b;
System.out.println(a + " / " + b + " = " + sum7);
double sum8 = c / d;
System.out.println(c + " / " + d + " = " + sum8);
- 取模运算符(
%
)- 用于求两个整数相除的余数。
int sum9 = a % b;
System.out.println(a + " % " + b + " = " + sum9);
double sum10 = c % d;
System.out.println(c + " % " + d + " = " + sum10);
注意事项:
- 当进行
整数除法
时,结果的小数部分会被丢弃,如果需要精确的小数结果,应确保操作数中至少有一个是浮点数类型。 - 在使用加法运算符
连接
字符串时,要注意操作数中至少有一个是字符串类型,否则会编译错误。 取模运算符
只能用于整数类型的操作数。- 运算符的优先级和结合性对于表达式的计算结果有重要影响。在复杂的表达式中,可以使用括号来明确运算顺序。
关系运算符
关系运算符用于比较两个值,并根据比较结果返回布尔值(true
或false
)。在Java中,这些运算符对于条件判断和决策控制非常重要。
- 等于运算符(
==
)- 检查两个值是否相等。
- 对于对象引用,检查两个引用是否指向同一个对象。
int x = 10;
int y = 20;
// 等于运算符
boolean isEqual = (x == y); // false
System.out.println("x 是否等于 y? " + isEqual);
- 不等于运算符(
!=
)- 检查两个值是否不相等。
- 对于对象引用,检查两个引用是否指向不同的对象。
// 不等于运算符
boolean isNotEqual = (x != y); // true
System.out.println("x 是否不等于 y? " + isNotEqual);
- 大于运算符(
>
)- 检查左侧的值是否大于右侧的值。
// 大于运算符
boolean isGreater = (x > y); // false
System.out.println("x 是否大于 y? " + isGreater);
- 小于运算符(
<
)- 检查左侧的值是否小于右侧的值。
// 小于运算符
boolean isLess = (x < y); // true
System.out.println("x 是否小于 y? " + isLess);
- 大于等于运算符(
>=
)- 检查左侧的值是否大于或等于右侧的值。
// 大于等于运算符
boolean isGreaterOrEqual = (x >= y); // false
System.out.println("x 是否大于或等于 y? " + isGreaterOrEqual);
- 小于等于运算符(
<=
)- 检查左侧的值是否小于或等于右侧的值。
// 小于等于运算符
boolean isLessOrEqual = (x <= y); // false
System.out.println("x 是否小于或等于 y? " + isLessOrEqual);
注意事项:
- 确保在使用等于运算符(
==
)比较对象时,你比较的是对象的内容而不是它们的引用。如果你想比较对象的内容,可能需要使用.equals()
方法。 - 当比较浮点数时,由于浮点数的精度问题,通常不建议使用
==
来比较两个浮点数是否相等。相反,应该检查两个浮点数之间的差值是否在一个很小的范围内。 - 在编写复杂的比较逻辑时,可以使用括号来明确运算顺序,避免因运算符优先级引起的逻辑错误。
- 关系运算符是控制程序流程的关键,它们在条件语句(如
if
、while
、for
)中扮演着重要角色。
逻辑运算符
逻辑运算符用于组合多个布尔表达式(关系运算),并根据这些表达式的结果执行逻辑判断。在Java中,逻辑运算符包括逻辑与(AND)、逻辑或(OR)和逻辑非(NOT)。
- 逻辑与(
&&
)- 当两个操作数都为
true
时,结果为true
。 - 它是短路运算符,如果第一个操作数为
false
,则不会评估第二个操作数,因为整个表达式的结果已经确定为false
。
- 当两个操作数都为
//定义变量
int i = 10;
int j = 20;
int k = 30;
//&& “逻辑与”,并且的关系,只要表达式中有一个值为false,结果即为false
System.out.println((i > j) && (i > k)); //false && false,输出false
System.out.println((i < j) && (i > k)); //true && false,输出false
System.out.println((i > j) && (i < k)); //false && true,输出false
System.out.println((i < j) && (i < k)); //true && true,输出true
- 逻辑或(
||
)- 当两个操作数中至少有一个为
true
时,结果为true
。 - 它也是短路运算符,如果第一个操作数为
true
,则不会评估第二个操作数,因为整个表达式的结果已经确定为true
。
- 当两个操作数中至少有一个为
//|| “逻辑或”,或者的关系,只要表达式中有一个值为true,结果即为true
System.out.println((i > j) || (i > k)); //false || false,输出false
System.out.println((i < j) || (i > k)); //true || false,输出true
System.out.println((i > j) || (i < k)); //false || true,输出true
System.out.println((i < j) || (i < k)); //true || true,输出true
- 逻辑非(
!
)- 用于反转布尔值,
true
变为false
,false
变为true
。
- 用于反转布尔值,
//! “非”,取反
System.out.println((i > j)); //false
System.out.println(!(i > j)); //!false,,输出true
注意事项:
- 短路行为:逻辑与(
&&
)和逻辑或(||
)运算符都具有短路行为,这意味着如果第一个操作数已经决定了整个表达式的结果,那么第二个操作数将不会被执行。这可以用于优化性能和避免不必要的计算。 - 逻辑非(
!
)运算符不具有短路行为,它总是会评估操作数。 - 在复杂的逻辑表达式中,使用括号来明确运算顺序,确保逻辑的正确性。
- 逻辑运算符在控制程序流程中起着至关重要的作用,特别是在处理条件语句时。
位运算
位运算符在Java中用于处理整数类型的二进制
表示(将整数转换成二进制,逐位进行处理)。它们直接对整数的每一位进行操作,非常适合进行位掩码和位字段的处理。以下是Java中的位运算符及其详解:
- 位与(
&
):- 对应的二进制位都为1时,结果才为1,否则为0。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
// 位与
int andRedult = a & b;// 结果为4,二进制: 0100
System.out.println("位与: " + andRedult);
- 位或(
|
):- 只要对应的二进制位中有一个为1,结果就为1。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
// 位或
int orResult = a | b;// 结果为15,二进制: 1111
System.out.println("位或: " + orResult );
- 位异或(
^
):- 对应的二进制位不相同时,结果为1,相同则为0。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
// 位异或
int xorResult = a ^ b; // 结果为11,二进制: 1011
System.out.println("位异或: " + xorResult);
- 位非(
~
):- 将操作数的每一位取反,1变为0,0变为1。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
// 位非
int notResult = ~a; // 结果为-13,二进制: 1001(注意:在Java中,位非运算符返回的是int类型)
System.out.println("位非: " + notResult);
- 左移(
<<
):- 将整数的二进制位向左移动指定的位数,右边用0填充。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
int leftShiftResult = a << 2; // 结果为48,二进制: 001100
System.out.println("左移: " + leftShiftResult);
- 右移(
>>
):- 将整数的二进制位向右移动指定的位数,左边用符号位填充(即保留符号)。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
int rightShiftResult = a >> 2; // 结果为3,二进制: 0011
System.out.println("右移: " + rightShiftResult);
- 无符号右移(
>>>
):- 将整数的二进制位向右移动指定的位数,左边用0填充,无论原始数是正还是负。
int a = 12; // 二进制: 1100
int b = 7; // 二进制: 0111
// 无符号右移
int unsignedRightShiftResult = a >>> 2; // 结果为3,二进制: 0011(无符号右移不保留符号)
System.out.println("无符号右移: " + unsignedRightShiftResult);
注意事项:
- 位运算符只适用于整数类型的数据(
byte
、short
、int
、long
)。 - 在进行位运算时,整数会被提升为
int
类型,如果需要对long
类型的数据进行操作,可以使用long
类型的变量。 - 位非运算符(
~
)在Java中返回的是int
类型的值,即使操作数是long
类型。 - 左移和右移运算符在移动位的同时,会根据移动的方向填充新的位。左移默认用0填充,而右移则用符号位填充。
- 无符号右移运算符(
>>>
)在移动位时始终用0填充,即使操作数是负数。 - 位运算符在处理位掩码和位字段时非常有用,例如在网络编程中设置或清除特定的位。
赋值运算符
赋值运算符用于将值分配给变量。在Java中,基本的赋值运算符是等号(=
),它用于将右侧表达式的结果赋给左侧的变量。除了基本的赋值运算符外,还有一系列复合赋值运算符,它们结合了算术运算和赋值操作。
基本赋值运算符(=
)
基本赋值运算符=
用于将一个值或表达式的结果存储在变量中。
int b = 5;
// 基本赋值运算符
int a = b + 4; // 将b+4的结果赋给a,a的值是9
System.out.println("a = "+a);
复合赋值运算符
复合赋值运算符是将算术运算符与赋值运算符结合在一起的简写形式。它们使代码更加简洁。以下是Java中的复合赋值运算符:
+=
:加法赋值,a += b
等同于a = a + b
。
int a = 10;
int b = 5;
// 加法赋值
a += b; // 等同于a = a + b,a 的值是 15
System.out.println("a = " + a);
-=
:减法赋值,a -= b
等同于a = a - b
。
int a = 10;
int b = 5;
// 减法赋值
a -= b; // 等同于a = a - b,a 的值是 5
System.out.println("a = " + a);
*=
:乘法赋值,a *= b
等同于a = a * b
。
int a = 10;
int b = 5;
// 乘法赋值
a *= b; // 等同于a = a * b,a 的值是 50
System.out.println("a = " + a);
/=
:除法赋值,a /= b
等同于a = a / b
。
int a = 10;
int b = 5;
// 乘法赋值
a /= b; // 等同于a = a / b,a 的值是 50
System.out.println("a = " + a);
%=
:取模赋值,a %= b
等同于a = a % b
。
int a = 10;
// 取模赋值
a %= 3; // 等同于a = a / 3,a 的值是 1
System.out.println("a = " + a);
&=
:位与赋值,a &= b
等同于a = a & b
。
- 运行逻辑:
- 首先,对
a
和b
进行位与运算(a & b
)。 - 位与运算的规则是:只有当两个操作数的相应位都为 1 时,结果位才为 1;否则,结果位为 0。
- 然后,将位与运算的结果赋值给变量
a
。
- 首先,对
- 应用场景
- 设置特定的位: 当你想要设置一个整数变量的特定位,同时保持其他位不变时,可以使用位与赋值运算。例如,如果你想要设置一个整数的第 3 位(从右往左数,从 0 开始),你可以使用一个掩码,该掩码在第 3 位上有 1,其他位上都是 0,然后与原整数进行位与赋值运算。
- 清除特定的位: 与设置位相反,如果你想要清除一个整数的特定位,可以使用一个掩码,该掩码在想要清除的位上是 0,其他位上都是 1。然后使用这个掩码与原整数进行位与赋值运算。
- 修改二进制表示: 在需要直接操作数据的二进制表示时,位与赋值运算符非常有用。例如,在网络编程中,你可能需要对 IP 地址或端口号的二进制表示进行修改。
// 位与赋值
int flags = 0b1101; // 十进制:13,二进制:1101
int mask = 0b1011; // 十进制:11,二进制:1011
// 设置第 1 位和第 3 位,清除第 0 位和第 2 位
flags &= mask; // 结果为 0b1001,十进制:9
System.out.println("flags 的十进制输出: " + flags);
|=
:位或赋值,a |= b
等同于a = a | b
。
- 运行逻辑:
- 首先,对
a
和b
进行位或运算(a | b
)。 - 位或运算的规则是:只要两个操作数的相应位中有一个为 1,结果位就为 1;如果两个位都为 0,则结果位为 0。
- 然后,将位或运算的结果赋值给变量
a
。
- 首先,对
- 操作场景:
- 设置特定的位: 当你想要设置一个整数变量的特定位,而不影响其他位的状态时,可以使用位或赋值运算。例如,如果你想设置一个整数的第 2 位(从右往左数,从 0 开始),你可以使用一个掩码,该掩码在第 2 位上有 1,其他位上都是 0,然后与原整数进行位或赋值运算。
- 修改标志位: 在处理包含多个标志位的位字段时,位或赋值运算符可以用来设置或清除特定的标志位。例如,在网络编程或设备驱动开发中,你可能需要设置或清除某些控制位以启用或禁用特定的功能。
- 合并位信息: 当你需要将两个整数的位信息合并到一个整数中时,可以使用位或赋值运算符。这样可以确保两个操作数中非零位的值都被保留。
// 位或运算
int status = 0b0010; // 十进制:2,二进制:0001 0010
int newFeature = 0b0100; // 十进制:4,二进制:0000 0100
// 通过位或赋值运算设置新特性位,同时保留其他位的状态
status |= newFeature; // 结果为 0b0110,十进制:6
System.out.println("status 的十进制值: " + status);
^=
:位异或赋值,a ^= b
等同于a = a ^ b
。
- 运行逻辑:
- 首先,对
a
和b
进行位异或运算(a ^ b
)。 - 位异或运算的规则是:两个操作数的相应位如果相同,则结果位为 0;如果相应位不同,则结果位为 1。
- 然后,将位异或运算的结果赋值给变量
a
。
- 首先,对
- 操作路径:
- 切换位状态: 位异或运算可以用来切换一个整数变量的特定位。如果你想切换一个位的状态(即从 0 变为 1,或从 1 变为 0),你可以使用一个掩码,该掩码在想要切换的位上有 1,其他位上都是 0,然后与原整数进行位异或赋值运算。
- 交换两个变量的值: 位异或运算可以用来在不使用临时变量的情况下交换两个变量的值。这是通过将两个变量相互异或,然后再次异或回原来的位置来实现的。
- 加密和安全: 位异或运算在某些简单的加密算法中也有应用,因为它可以改变数据的位模式,从而提供一定程度的安全性。
// 位运算的复合赋值
int a = 0b1101; // 十进制:13,二进制:1101
int b = 0b1011; // 十进制:11,二进制:1011
// 切换 a 的第 2 位的状态
int mask = 0b0100; // 掩码,第 2 位为 1,其他位为 0
a ^= mask; // 结果为 0b1001,十进制:9
System.out.println("a 当前的值: " + a);
// 交换 a 和 b 的值
a ^= b;
b ^= a;
a ^= b; // 现在 a 是原始的 b,b 是原始的 a
System.out.println("a 当前的值 " + a); // 输出原始 b 的值
System.out.println("b 当前的值: " + b); // 输出原始 a 的值
>>=
:右移赋值,a >>= b
等同于a = a >> b
。
- 运行逻辑:
- 首先,对
a
进行带符号右移运算(a >> b
)。 - 带符号右移运算的规则:将整数的二进制表示向右移动指定的位数,左边用符号位填充(即,如果
a
是正数,左边填充 0;如果a
是负数,左边填充 1)。 - 然后,将右移运算的结果赋值给变量
a
。
- 首先,对
- 操作场景:
- 位字段操作: 在处理位字段或标志位时,右移赋值运算符可以用来移动位字段的位置或清除特定的位。
- 缩放数值: 右移运算实际上对数值进行了除以 2 的幂次方的操作(因为每向右移动一位,就相当于除以 2)。因此,可以用右移赋值来缩放数值,特别是当你需要对数值进行快速除法运算时。
- 实现某些算法: 在某些算法中,例如快速傅里叶变换(FFT)或其他需要频繁进行位操作的算法中,右移赋值运算符可以用来优化性能。
int a = -10; // 假设我们有一个负数 a,其二进制表示为 1110 1010(32位)
int b = 2; // 我们将 a 向右移动 2 位
// 执行右移赋值操作
a >>= b; // 结果为 1111 1111 1111 1111 1111 1111 1111 1110,即 -1
System.out.println("a = " + a);
>>>=
:无符号右移赋值,a >>>= b
等同于a = a >>> b
。
- 运行逻辑:
- 首先,对
a
进行无符号右移运算(a >>> b
)。 - 无符号右移运算的规则:将整数的二进制表示向右移动指定的位数,左边始终用 0 来填充。
- 然后,将无符号右移运算的结果赋值给变量
a
。
- 首先,对
- 操作场景:
- 处理无符号整数: 当你在处理无符号整数(例如,原始类型
int
可以被视为无符号整数)时,使用无符号右移可以确保在移动位时不改变数的符号。 - 位字段操作: 在位字段操作中,无符号右移可以用来移动位字段的位置,同时保持高位的 0 状态,这在某些硬件编程或网络编程中很有用。
- 性能优化: 在某些情况下,使用无符号右移可以提高性能,因为它避免了带符号右移可能涉及的符号位扩展操作。
- 处理无符号整数: 当你在处理无符号整数(例如,原始类型
int a = -10; // 假设我们有一个负数 a,其二进制表示为 1110 1010(32位)
int b = 2; // 我们将 a 无符号右移 2 位
// 执行无符号右移赋值操作
a >>>= b; // 结果为 0001 1111 1111 1111 1111 1111 1110,即 1073741822
System.out.println("a = " + a);
<<=
:左移赋值,a <<= b
等同于a = a << b
。
- 运行逻辑
- 首先,对
a
进行左移运算(a << b
)。 - 左移运算的规则是:将整数的二进制表示向左移动指定的位数,右边用 0 来填充。
- 然后,将左移运算的结果赋值给变量
a
。
- 首先,对
- 操作场景
- 缩放数值: 左移运算实际上对数值进行了乘以 2 的幂次方的操作(因为每向左移动一位,就相当于乘以 2)。因此,可以用左移赋值来缩放数值,特别是当你需要对数值进行快速乘法运算时。
- 位字段操作: 在处理位字段或标志位时,左移赋值运算符可以用来移动位字段的位置或清除特定的位。
- 优化性能: 在某些情况下,使用左移运算可以提高性能,因为它是一种快速的乘法方法,特别是当处理无符号整数时。
int a = 5; // 十进制:5,二进制:0101
int b = 2; // 我们将 a 向左移动 2 位
// 执行左移赋值操作
a <<= b; // 结果为 0101 0000,即十进制的 20
System.out.println("a = " + a);
条件运算符
条件运算符,也称为三元运算符
,是Java中的一个特殊运算符,它提供了一种简洁的方式来根据条件表达式的结果来选择两个值中的一个。条件运算符的一般形式是:
condition ? expression1 : expression2;
condition
:是一个布尔表达式。expression1
:可以是任意类型的表达式。如果condition
为true
,则条件运算符的结果为expression1
的值。expression2
:可以是任意类型的表达式。如果condition
为false
,则结果为expression2
的值。
int score = 85;
// 使用条件运算符来计算等级
// 如果分数大于等于60,则等级为"及格";否则等级为"不及格"
String grade = score >= 60 ? "及格" : "不及格";
System.out.println("学生的等级是: " + grade); // 输出 "学生的等级是: 及格"