[Java · 初窥门径] 运算符 — 位运算符

#新星杯·14天创作挑战营·第10期#

🌟 想系统化学习 Java 编程?看看这个:[编程基础] Java · 学习手册

✅ 提示:本章只是作为一个了解技能点,如果小伙伴没看懂,可以跳过此技能点。

0x01:位运算符 — 概览

位运算符主要针对的是二进制数,对二进制数的所有位数依次从低位到高位进行运算。 在进行位运算时,会涉及补码到原码的转换(只有转换成原码后才能转换为十进制数)。二进制正数的补码与原码形式相同,负数的补码要想转化为原码,需要对补码进行取反后加一的操作。


本章我们涉及的运算符如下表多是,读者可以按需学习,如果都理解,可以快速跳过:

类别符号说明
位运算符&按位与
位运算符|按位或
位运算符~按位取反
位运算符^按位异或
位运算符<<按位左移,左移 1 位相当于乘 2
位运算符>>按位右移,右移 1 位相当于除 2 取商
位运算符>>>按位无符号右移

从上方的表格可以看出,位运算符的 &、|、^ 与我们前面在逻辑运算符中讲的逻辑与、逻辑或、逻辑异或长得一摸一样,那么问题来了,我们实战中如何区分,哪个是位运算符?哪个是逻辑运算符呢?实战中,我们一般是通过运算符左右连接的数据类型来判断运算符的作用的:

  • 逻辑运算符: 左右连接的是布尔类型的操作数。

  • 位运算符: 左右连接的是具体的数值。

0x02:位运算符 — 详解

由于位运算符操作的是二进制数,所以下面的分析需要读者掌握十进制与二进制之间的转换。并且,由于计算机存储数据采用的是内存,所以读者还需要知道每种数据类型在内存中的存储格式,以及原码、补码与反码的相关概念。

笔者这里为了方便读者理解,将采用 byte 类型(在内存中占 1 个字节,即 8 位)进行演示。

0x0201:位运算符 & 详解

& 的运算法则位:两个二进制操作数只有对应的位都为 1 时,结果位才为 1,否则为 0。两个二进制数的按位与运算示例如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = 0b01001000;
        System.out.println(num1 & num2);
    }
}

0x0202:位运算符 | 详解

| 运算的法则为:两个二进制操作数只有对应的位都为 0 时,结果位才为 0,否则为 1。两个二进制数的按位或运算示例如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = 0b01001000;
        System.out.println(num1 | num2);
    }
}

0x0203:位运算符 ~ 详解

~ 的运算法则为:将操作数中的二进制数 1 变为 0,0 变为 1。二进制数的按位取反运算示例如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        System.out.println(~num1);
    }
}

0x0204:位运算符 ^ 详解

^ 的运算法则为:若两个二进制操作数对应的位相同(同为 0 或同为 1)时,结果位为 0,否则为 1。两个二进制数按位异或运算示例如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = 0b01001000;
        System.out.println(num1 ^ num2);
    }
}

0x0205:位运算符 << 详解

<< 的运算符法则为:将一个二进制数向左移动指定的位数。左边(高位)溢出的位数会被丢弃,右边(低位)空出的位置用 0 填补。按位左移相当于乘以 2 的 n 次幂。二进制数的按位左移运算示例如下(负数的补码到十进制数的转换有点特殊):

上面我们给的案例比较特殊,涉及到了计算机基础的源码、反码与补码的运算。如果读者不清楚,可以尝试问 AI “byte 型数据 01000001 左移一位,推导流程是咋样的,我要十进制结果”,AI 会很乐意告诉你推导流程的。这里我们直接上代码验证:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = (byte) (num1 << 1);
        System.out.println(num2);
        byte num3 = (byte) (num1 << 2);
        System.out.println(num3);
    }
}

0x0206:位运算符 >> 详解

>> 的运算法则为:将一个二进制操作数向右移动指定的位数。右边(低位)溢出的位数会被丢弃,对于左边(高位)空出的位置。如果最高位是 0(正数),则左侧填充 0,如果最高位是 1(负数),则左侧填充 1。按位右移相当于除以 2 的 n 次幂。二进制数的按位右移运算示例如下:

上面这个案例就比较简单了,没有涉及负数的补码与原码转换。对应的程序如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = (byte) (num1 >> 1);
        System.out.println(num2);
        byte num3 = (byte) (num1 >> 2);
        System.out.println(num3);
    }
}

0x0207:位运算符 >>> 详解

>>> 的运算法则为:将一个二进制操作数向右移动指定的位数。右边(低位)溢出的位数会被丢弃,对于左边(高位)空出的位置,直接补 0(简而言之,就是符号位也参与运算)。二进制数按位无符号右移运算示例如下:

public class TestVar {
    public static void main(String[] args) {
        byte num1 = 0b01000001;
        byte num2 = (byte) (num1 >>> 1);
        System.out.println(num2);
        byte num3 = (byte) (num1 >>> 2);
        System.out.println(num3);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blue17 :: Hack3rX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值