运算符介绍
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等
算术运算符
算术运算符是对数值类型的变量进行运算的
常用的运算符有以下几个:
注意:% 的本质:看一个公式 a % b = a - a / b * b(注意先乘除后加减);当a和b都是小数或其中一个是小数,会有一个强转,即公式变为 a % b = a - (int)(a / b) * b
public class Test {
public static void main(String[] args){
// 除号(/)的使用
// 10 和 4 两个操作数都是int类型,所以运算结果最高也是int类型,所以只取2.5的整数部分,即2
System.out.println(10 / 4); // 2
// 10.0 为double,4位int,整个运算结果为double类型,所以结果为2.5
System.out.println(10.0 / 4); // 2.5
double d = 10.0 / 4;
System.out.println(d); // 2.5
// 10 和 4 两个操作数都是int类型,所以运算结果最高也是int类型,所以只取2.5的整数部分,即2
// 赋值给double类型后,将2转换为double类型,变为2.0
double d1 = 10 / 4;
System.out.println(d1); // 2.0
// 针对以下两个式子,有个疑问:
// 为什么都是除得尽的情况,10.1 / 5 得到的是2.02这个刚好除得尽的结果,而8.1 / 3得到的却是一个近似值
System.out.println(10.1 / 5); // 2.02
double d2 = 8.1 / 3;
System.out.println(d2); // 2.6999999999999997
// 取余(%)
// % 的本质:看一个公式 a % b = a - a / b * b(注意先乘除后加减)
// 10 % 3 = 10 - 10 / 3 * 3 = 10 - 3 * 3 = 10 - 9 = 1 (注意!!在Java中 10 / 3 = 3,不是除不尽)
System.out.println(10 % 3); // 1
// -10 - (-10) / 3 * 3 = -10 - (-3) * 3 = -10 - (-9) = -10 + 9 = -1
System.out.println(-10 % 3); // -1
// 10 - 10 / (-3) * (-3) = 10 - (-3) * (-3) = 10 - 9 = 1
System.out.println(10 % -3); // 1
// -10 - (-10) / (-3) * (-3) = -10 - 3 * (-3) = -10 - (-9) = -1
System.out.println(-10 % -3); // -1
// 自增的两个经典面试题,自减和自增同理
// 第一题
int i = 1;
// 以下运算是先赋值在自增
// 计算机内部会使用一个临时变量存储结果:(1)temp = i;(i初始为1) (2)i = i + 1; (3)i = temp;
// 相当于 j = i++; (1)temp = i;(i初始为1) (2)i = i + 1; (3)j = temp;
i = i++;
System.out.println(i); // 1
// 第二题
int i1 = 1;
// 以下结果是先自增再赋值
// (1)i1 = i1 + 1; (2)temp = i1; (3)i1 = temp;
// 相当于 j = ++i1; => (1)i1 = i1 + 1; (2)temp = i1; (3)j = temp;
i1 = ++i1;
System.out.println(i1); // 2
}
}
关系运算符(比较运算符)
- 关系运算符的结果都是boolean型,要么是true,要么是false
- 关系表达式经常用在if结构的条件中或者循环结构的条件中
- 关系运算符组成的表达式,成为关系表达式
逻辑运算符
- 短路与 &&,短路或 ||,取反 !
- 逻辑与 &,逻辑或 |,逻辑异或 ^
- 短路与和逻辑与的区别:当第一个条件为假时,短路与不会对第二个条件进行判断,而逻辑与则是不管第一个条件是真是假,都会对第二个条件进行判断
- 同理,短路或是当第一个条件为真时,不会对第二个条件进行判断,而逻辑或是不管第一个条件是真是假,都会对第二个条件进行判断
- 异或:只有两个条件不一样时为真
如下表所示:
赋值运算符
- 基本赋值运算符:=
- 复合赋值运算符:+=、-=、/=、*=、%=
- 赋值运算符的特点:
三元运算符
- 基本语法:条件表达式 ? 表达式1 : 表达式2,条件表达式为true,返回表达式1的运算结果,否则返回表达式2的运算结果
运算符优先级
下表的优先级从上往下依次降低
位运算符
java中有7个位运算符:
- & 按位与:两位全为1,结果为1,否则为0
- | 按位或:两位有一位为1,结果为1,否则为0
- ^ 按位异或:两位一个为0,一个为1,结果为1,否则为0
- ~ 按位取反:0变为1, 1变为0
public class Test {
public static void main(String[] args){
// 推导
// 计算机中的所有运算都是以补码的形式进行计算,结果是以原码形式输出
// 1、求 2 的补码,先要求出 2 的原码,再求 2 的反码,最后求 2 的补码
// 2 是int类型,占四个字节,2 的原码 00000000 00000000 00000000 00000010
// 由于 2 是正数,所以三码合一
// 2 的补码为 00000000 00000000 00000000 00000010
// 同理,3 的补码为 00000000 00000000 00000000 00000011
// 按位与的结果为 00000000 00000000 00000000 00000010 (该结果为补码)
// 因为上述补码运算结果为正数(符号位为0),三码合一
// 所以上述补码的的原码为 00000000 00000000 00000000 00000010
// 转为十进制,推导出的输出结果为2
System.out.println(2 & 3); // 2
// 求 -2 的补码,先要求出 -2 的原码,再求 -2 的反码,最后求 -2 的补码
// 负数的原码求补码可用一个技巧:从右边数第一个1及其右边保持不变,左边按位取反(符号位不取反)
// -2 是int类型,占四个字节,-2 的原码 10000000 00000000 00000000 00000010
// -2 的补码为 11111111 11111111 11111111 11111110
// ~-2操作:按位取反 00000000 00000000 00000000 00000001 (该结果为补码)
// 将上述结果为正数,三码合一,所以转变为原码为 00000000 00000000 00000000 00000001
// 转为十进制,推导出的输出结果为1
System.out.println(~-2); // 1
// 2 是int类型,占四个字节,2 的原码 00000000 00000000 00000000 00000010
// 三码合一,2 的补码为 00000000 00000000 00000000 00000010
// ~2操作:按位取反 11111111 11111111 11111111 11111101 (该结果为补码)
// 将上述结果为负数,所以转变为原码为 10000000 00000000 00000000 00000011
// 转为十进制,推导出的输出结果为-3
System.out.println(~2); // -3
// 按位或、按位异或同理
// 2 的原码 00000000 00000000 00000000 00000010
// 3 的原码 00000000 00000000 00000000 00000011
// 三码合一
// 2 的补码 00000000 00000000 00000000 00000010
// 3 的补码 00000000 00000000 00000000 00000011
// 2 ^ 3结果 00000000 00000000 00000000 00000001 (运算结果为补码)
// 补码为正数,所以原码也为 00000000 00000000 00000000 00000001
// 对应的十进制为 1
System.out.println(2 ^ 3); // 1
}
}
- >> 算术右移:低位溢出,符号位不变,并用符号位补溢出的高位
- << 算术左移:符号位不变,低位补0
- >>> 逻辑右移,也叫无符号右移:低位溢出,高位补0
-
没有 <<< 符号 的
public class Test {
public static void main(String[] args){
// 1 右移 2 位,本质是 1 / 2 / 2 = 0
// 1 的补码:00000000 00000000 00000000 00000001
// 右移两位,低位溢出,符号位不变,用符号位补溢出的高位
// 所以结果为 00000000 00000000 00000000 000000 00(符号位补溢出的位置) 01(溢出,直接丢弃)
// 上述补码结果还是正数,所以源码也为00000000 00000000 00000000 00000000
// 结果为0
System.out.println(1 >> 2); // 0
// 1 左移 2 位,本质是 1 * 2 * 2 = 4
// 1 的补码:00000000 00000000 00000000 00000001
// 左移两位,不溢出的情况下符号位不变,低位补0
// 所以结果为 00000000 00000000 00000000 00000001 00(低位补0)
// 上述补码结果还是正数,所以源码也为00000000 00000000 00000000 00000001 00
// 结果为4
System.out.println(1 << 2); // 4
// 低位溢出,高位补0
// 2 的补码 00000000 00000000 00000000 00000010
// 逻辑右移 3 位 000(高位补0) 00000000 00000000 00000000 00000 010(丢弃)
System.out.println(2 >>> 3); // 0
}
}