深入理解Java中的位运算符

哈喽,各位小伙伴们,你们好呀,我是喵手。

今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

Java是一门广泛使用的编程语言,拥有丰富的运算符来支持代码的实现。位运算符是其中的一类,它们在处理整数类型的数据时十分有用,也是Java开发中经常用到的运算符之一。

摘要

本文将深入介绍Java中的位运算符,包括按位与、按位或、按位异或、按位取反、左移、右移等,同时详细解析它们的用法和实现原理,并通过实例演示如何应用位运算符来解决程序中的实际问题。此外,本文还将分析位运算符的优缺点,展示它们在编程中的一些常见应用场景,以及实现位运算的相关类和方法。

Java之位运算符

简介

Java中的位运算符是用来对二进制数进行运算的。在进行位运算时,首先需要将数值转换为二进制,然后对它们进行特定的计算,最后将结果转换回十进制数。Java中的位运算符有六种,分别为按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>),下面将分别讲解其用法和实现原理。

按位与(&)

按位与运算符(&)的作用是将操作数的每个对应位都进行与运算,结果位的值为1只有当两个操作数对应位都为1时才会出现。例如:

java 复制代码
int a = 5; //101二进制表示
int b = 3; //011二进制表示

int result = a & b; //001二进制表示,即1

按位或(|)

按位或运算符(|)的作用是将操作数的每个对应位都进行或运算,结果位的值为1只要有一个操作数对应位为1就会出现。例如:

java 复制代码
int a = 5; //101二进制表示
int b = 3; //011二进制表示

int result = a | b; //111二进制表示,即7

按位异或(^)

按位异或运算符(^)的作用是将操作数的每个对应位都进行异或运算,结果位的值为1只有当两个操作数对应位不同才会出现。例如:

java 复制代码
int a = 5; //101二进制表示
int b = 3; //011二进制表示

int result = a ^ b; //110二进制表示,即6

按位取反(~)

按位取反运算符(~)的作用是将操作数的每个对应位都进行取反操作(0变成1,1变成0)。例如:

java 复制代码
int a = 5; //101二进制表示

int result = ~a; //即010二进制表示,即-6

需要注意的是,按位取反运算符(~)的结果是一个负数。

左移(<<)

左移运算符(<<)的作用是将操作数的二进制位向左移动指定的位数,空位补0。例如:

java 复制代码
int a = 5; //101二进制表示

int result = a << 2; //即10100二进制表示,即20

右移(>>)

右移运算符(>>)的作用是将操作数的二进制位向右移动指定的位数,空位的值由符号位决定,正数补0,负数补1。例如:

java 复制代码
int a = 20; //10100二进制表示

int result = a >> 2; //即00101二进制表示,即5

需要注意的是,右移运算符(>>)会保留符号位,因此对于负数来说,右移运算会使结果变小,而对于正数来说,右移运算会使结果变大。

源代码解析

下面是一些实际使用位运算符的Java源代码,演示了它们的具体用法:

按位与(&)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 5; //101二进制表示
        int b = 3; //011二进制表示

        int result = a & b; //001二进制表示,即1
        System.out.println(result);
    }
}

代码解析:

这段代码表示对两个整数变量a和b进行按位与运算。具体来说,a和b的二进制表示分别为101和011,进行按位与运算后,得到的二进制结果为001,即1,将该结果赋值给result变量,然后输出result变量的值,即1。因此,该段代码的输出结果为1。

按位或(|)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 5; //101二进制表示
        int b = 3; //011二进制表示

        int result = a | b; //111二进制表示,即7
        System.out.println(result);
    }
}

代码解析:

这段代码定义了一个Test类,包含了main方法。在main方法中,首先定义了两个整型变量a和b,分别赋值为5和3。

然后使用位运算符"|"对变量a和b进行位或操作,将它们的二进制表示对应位上的值分别进行或运算,得到的结果为7,即111二进制表示。

最后,使用System.out.println()方法输出结果7。因此,程序的输出结果为7。

按位异或(^)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 5; //101二进制表示
        int b = 3; //011二进制表示

        int result = a ^ b; //110二进制表示,即6
        System.out.println(result);
    }
}

代码解析:

此代码是一个简单的Java程序,它定义了一个名为Test的公共类,其中有一个名为main的公共静态void方法,该方法在程序运行时被调用。

在main方法中,定义了两个整型变量a和b,分别赋值为5和3。接下来,使用异或运算符^对a和b进行异或运算,并将结果赋值给result变量。异或运算的规则是,如果两个位上的值相同,则结果为0,否则为1。将a和b转换为二进制后,可以知道它们的二进制表示分别为101和011。将它们按位进行异或运算,得到的结果为110,也就是二进制的6。

最后,程序将结果打印到控制台上,输出为6。

按位取反(~)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 5; //101二进制表示

        int result = ~a; //即010二进制表示,即-6
        System.out.println(result);
    }
}

代码解析:

这段代码演示了Java中的按位取反运算符(~) 的用法。该运算符将操作数的二进制表示中的每个位取反,即0变为1,1变为0。在该代码中,变量a被赋值为5,其二进制表示为101。因此,按位取反运算符将其转换为010,即2的补码表示。该结果在Java中被解释为带符号的整数,因此其数值为-6。因此,当该程序运行时,~a的值为-6,并被打印到控制台上。

左移(<<)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 5; //101二进制表示

        int result = a << 2; //即10100二进制表示,即20
        System.out.println(result);
    }
}

代码解析:

这段代码定义了一个名为Test的公共类,其中包含了一个名为main的公共静态方法。

在main方法中,定义了一个整数变量a并赋值为5,即二进制表示为101。

然后使用位运算符<<对a进行左移2位操作,将结果赋值给一个名为result的整数变量。左移运算符<<将二进制数向左移动指定的位数,并在低位补零。即将101左移2位得到10100,即20十进制表示。

最后,使用System.out.println()方法将result的值输出到控制台。

因此,程序运行后将输出20。

右移(>>)

java 复制代码
public class Test {
    public static void main(String[] args) {
        int a = 20; //10100二进制表示

        int result = a >> 2; //即00101二进制表示,即5
        System.out.println(result);
    }
}

代码解析:

这段代码实现了将一个整数a右移两位的操作,并将结果输出。

首先,定义了一个整型变量a并赋值为20,即二进制表示为10100。接着,使用右移运算符(>>)将a向右移动了两位,即将a中的每一位向右移动两位,并将空出来的两位补零。这样,a的二进制表示就变成了00101,即十进制的5。最后,将结果5输出。

应用场景案例

位运算符在Java开发中有很多实际应用场景,下面列举一些比较常见的应用案例:

奇偶性判断

判断一个数是奇数还是偶数,可以使用按位与运算符(&)。因为偶数的二进制末位为0,奇数的二进制末位为1,因此可以将给定的数值与1进行按位与运算,如果结果为0,则是偶数,否则是奇数。例如:

java 复制代码
public class Test {
    public static boolean isEven(int num) {
        return (num & 1) == 0; //如果结果为0,则是偶数,否则是奇数
    }

    public static void main(String[] args) {
        System.out.println(isEven(4)); //输出true
        System.out.println(isEven(5)); //输出false
    }
}

代码解析:

该代码定义了一个名为Test的类,包含了一个静态方法isEven。isEven方法接收一个参数num,返回一个布尔值。如果num为偶数,返回true,否则返回false。

isEven方法的实现是利用位运算的性质:偶数的二进制末位为0,奇数的二进制末位为1。使用与运算(&)将num与1进行运算,如果结果为0,则num是偶数,否则是奇数。

在main方法中,分别调用isEven方法,并输出其返回值,可以得到4是偶数,5是奇数的结论。

交换两个数的值

交换两个数的值可以使用按位异或运算符(^)。因为异或运算规则是:两个二进制位不同则结果为1,相同则为0,因此可以通过异或运算来交换两个数的值,同时不需要使用额外的变量。例如:

java 复制代码
public class Test {
    public static void swap(int a, int b) {
        a ^= b; //a = a ^ b
        b ^= a; //b = b ^ (a ^ b) = a ^ b ^ b = a
        a ^= b; //a = (a ^ b) ^ a = b

        System.out.println("a = " + a + ", b = " + b);
    }

    public static void main(String[] args) {
        swap(5, 3); //输出a = 3, b = 5
    }
}

代码解析:

这段代码实现了不使用第三个变量来交换两个整数的值。它使用了位运算中的异或操作(^)来达到目的。

首先,将a和b进行异或操作,得到结果保存在a中:a = a ^ b。然后,将b和(a ^ b)进行异或操作,得到结果保存在b中:b = b ^ (a ^ b) = a ^ b ^ b = a。最后,再次将a和b进行异或操作,得到结果保存在a中:a = (a ^ b) ^ a = b。

这样,a和b的值就被成功地交换了。在main函数中,调用swap函数,传入参数5和3,输出结果为a = 3, b = 5。

字符串的快速比较

Java中的字符串比较通常使用equals()方法,但是这种方式效率比较低,因为它需要逐个比较每个字符,而使用位运算符可以快速比较两个字符串是否相等。具体实现是将两个字符串的每个字符按位异或,然后将所有结果按位与运算,如果结果为0,则表示两个字符串相等。例如:

测试代码演示

java 复制代码
package com.example.javase.se.operators;

/**
 * @Author ms
 * @Date 2023-11-07 22:30
 */
public class BitwiseOperatorDemo {

    public static boolean isEqual(String str1, String str2) {
        if (str1 == null || str2 == null || str1.length() != str2.length()) {
            return false;
        }

        int result = 0;
        for (int i = 0; i < str1.length(); i++) {
            result ^= str1.charAt(i) ^ str2.charAt(i);
        }

        return result == 0;
    }

    public static void main(String[] args) {
        System.out.println(isEqual("hello", "hello")); //输出true
        System.out.println(isEqual("hello", "world")); //输出false
    }
}

测试结果

根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

测试代码分析

根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。   这段代码实现了一个比较两个字符串是否相等的方法。它使用了位运算符,具体来说是异或运算符(^)。

方法 isEqual() 接收两个字符串参数,如果其中任意一个字符串为空或者两个字符串长度不相等,就返回 false。否则,它会对两个字符串的每个字符进行异或运算,并将结果保存到 result 变量中。如果最终 result 等于 0,说明两个字符串相等,返回 true;否则返回 false。

在 main() 方法中,使用 isEqual() 方法比较了两组字符串,结果分别是 true 和 false。

优缺点分析

位运算符的主要优点是效率高,可以快速处理整数类型的数据。另外,位运算符还可以用来进行特定的数据操作,比如判断奇偶性、交换两个数的值、字符串比较等,能够提高代码的灵活性和可读性。

然而,位运算符的主要缺点是可读性不够好,因为操作的都是二进制位,需要进行繁琐的转换计算,容易出现错误。同时,位运算符在处理负数时需要特别注意符号位的处理,容易引起错误。

相关类和方法

Java中提供了一些相关的类和方法来实现位运算的功能,下面简单介绍一些常用的:

  • Integer类:Java中的Integer类提供了一些方法来进行位运算,比如bitCount()方法可以计算一个整数的二进制表示中1的个数,highestOneBit()方法可以返回一个整数的最高位1的位置等等。
  • BitSet类:Java中的BitSet类实现了一套位向量的操作方法,可以方便地对二进制位进行操作,包括设置、清除、翻转、查找等。
  • Math类:Java中的Math类提供了一些方法来进行数值计算,其中包括了位运算相关的方法,比如max()和min()方法可以返回两个整数中的最大值和最小值,还有abs()方法可以返回一个整数的绝对值。

小结

本文介绍了Java中的位运算符,包括按位与、按位或、按位异或、按位取反、左移、右移等。同时还详细解析了它们的用法和实现原理,并通过实例演示如何应用位运算符来解决程序中的实际问题。此外,本文还分析了位运算符的优缺点,展示了它们在编程中的一些常见应用场景,以及实现位运算的相关类和方法。最后,建议在使用位运算符时一定要仔细确认数据的符号位和二进制位,避免出现错误。

总结

本文介绍了Java中的位运算符,包括按位与、按位或、按位异或、按位取反、左移、右移等。同时还详细解析了它们的用法和实现原理,并通过实例演示如何应用位运算符来解决程序中的实际问题。此外,本文还分析了位运算符的优缺点,展示了它们在编程中的一些常见应用场景,以及实现位运算的相关类和方法。在使用位运算符时,需要仔细确认数据的符号位和二进制位,避免出现错误。如果想学习Java编程,掌握位运算符是非常重要的一步。

... ...

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

... ...

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

相关推荐
苹果醋38 分钟前
AI大模型竞赛升温:百度发布文心大模型4.5和X1
java·运维·spring boot·mysql·nginx
网安INF12 分钟前
CVE-2020-1938源码分析与漏洞复现(Tomcat 文件包含/读取)
java·网络·web安全·网络安全·tomcat·漏洞复现
nenchoumi311924 分钟前
UE5 学习系列(九)光照系统介绍
java·学习·ue5
江梦寻27 分钟前
软件工程教学评价
开发语言·后端·macos·架构·github·软件工程
张乔2435 分钟前
spring boot项目整合mybatis实现多数据源的配置
java·spring boot·多数据源
GzlAndy39 分钟前
Tomcat调优
java·tomcat
美好的事情能不能发生在我身上41 分钟前
苍穹外卖Day11代码解析以及深入思考
java·spring boot·后端·spring·架构
辉辉健身中1 小时前
Maven入门(够用)
java·maven
星火飞码iFlyCode1 小时前
【无标题】
java·前端·人工智能·算法
不良手残1 小时前
Redisson + Lettuce 在 Spring Boot 中的最佳实践方案
java·spring boot·redis·后端