Java中的byte & 0xff到底有什么作用?

 更新时间:2021年06月23日 14:38:41   作者:小楼夜听雨QAQ  
这篇文章主要介绍了Java中的byte & 0xff到底有什么作用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

如果写过通信类的代码,比如socket编程,应该对这个问题不陌生。

先说结论

byte & 0xff 是将byte从(-128 至 127)转化成 int(转化后的数值范围: 0 至 255)。

其实就是1个byte有两种表示方法,我们既可以用-128 - 127这段范围来表示一个字节,也可以用 0 - 255这个范围的数来表示一个字节。

看一个demo

用Java中的InetAddress类来获取我当前的ip

public class InetAddressTest { 
    public static void main(String[] args) throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        byte[] address = localHost.getAddress();
        for (byte b : address) {
            System.out.print(b + " ");
        }
    }
}

输出结果

-64 -88 2 119

本机ip

好像不太一样,我们ip地址只用 0 - 255来表示,不会出现负数。

所以再换一种写法,将取出来的字节 & 0xff

public class InetAddressTest { 
    public static void main(String[] args) throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        byte[] address = localHost.getAddress();
        for (byte b : address) {
            System.out.print( ( b & 0xff ) + " ");
        }
    }
}

结果

192 168 2 119

Process finished with exit code 0

果然就是我们想要的结果

为什么需要转换

因为Java中的byte是有符号的,他的范围只能是 -128 - 127。

我们在使用tcp等协议的时候,首先要把传输的消息转化成字节流,然后再传输,在编程语言中字节流通常用十进制的byte数组来表示。

假如我们就想用 0-255来表示一个字节,不想用负数,该怎么办呢?

可惜Java中没有 无符号字节(unsigned byte), 我们只能用 int 来存储0-255。

而int的范围是(-2^31 ~ 2^31-1),只用了256个,剩下的空间都被浪费了,得不偿失啊。

所以我们存储的时候、传输的时候可以用byte,但是使用的时候就需要做一个转换了,那为什么0xff就可以得到无符号byte呢。

& 0xff的作用

作为一个十六进制数,0xff在Java中是用什么类型存储的呢?

应该显而易见吧,0xff是整型。

假设我现在要转化 字节 -1

-1的原码、反码、补码分别如下:

原码  1 0 0 0  0 0 0 1
反码  0 1 1 1  1 1 1 0
补码  0 1 1 1  1 1 1 1

现在和 0xff做运算, ff 就是(1111 11111),而因为他是整型,占4个字节,32为,所以0Xff的前面还有24个0。

用 -1 的补码进行计算

-1                                      0 1 1 1  1 1 1 1
0xff     000000000 000000000 000000000  1 1 1 1  1 1 1 1
=        000000000 000000000 000000000  0 1 1 1  1 1 1 1
=        255

其实在Java中,”任何数 & 0Xff等于那个数本身“ 这句话就显得不那么正确了

”任意整型 & 0xff = 本身“ 是没有问题的

但是字节 & 0xff 就被拖到了另一个次元,从byte进化成了int。

关于byte[ ] & 0xFF的问题

最近在写有关SHA256加密解密的问题,发现有一段代码是这样的,处于好奇理解了一下。

private static String byte2Hex(byte[] bytes){
  StringBuffer stringBuffer = new StringBuffer();
  String temp = null;
  for (int i=0;i<bytes.length;i++){
   temp = Integer.toHexString(bytes[i] & 0xFF);
   if (temp.length()==1){
    //1得到一位的进行补0操作
    stringBuffer.append("0");
   }
   stringBuffer.append(temp);
  }
  return stringBuffer.toString();
 }

Integer类中toHexString方法的参数是int类型,为什么byte[ ] & 0xFF可以表示int类型呢?

byte[i]是8位二进制,0xFF转化为8位二进制为11111111,& 之后的结果还是本身啊,这是怎么回事?

我们都知道计算机内的存储都是利用二进制的补码进行存储的。

复习一下,原码反码补码这三个概念

对于一个字节的最高位,计算机中是有规定的,正数的最高位为0,负数的最高位为1。

对于正数(00000001)原码来说,首位表示符号位,反码 补码都是本身

对于负数(100000001)原码来说,反码是对原码除了符号位之外作取反运算即(111111110),补码是对反码作+1运算即(111111111)

下面写段代码测试下

public static void main(String[] args) {
  byte[] a=new byte[10];
  a[0]=-127;
  System.out.println("a[0]:"+a[0]);
  int b=a[0] & 0xFF;
  System.out.println("b:"+b);
 }

得到的结果为:

a[0]:-127

b:129

现在针对这个结果进行分析:

byte类型的a[0]的值为-127,在计算机中存储的补码为:10000001,这个补码是8位的,而int类型是32位的,所以a[0]作为int类型来输出的时候jvm给做了个补位便成了 111111111111111111111111 10000001(-127),虽然补码转换了,但是这两个补码表示的十进制数字是相同的。

为了保证二进制数据的一致性,当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化,而&0xFF可以将高的24位置为0,低8位保持原样。

int b = a[0]&0xff; a[0]&0xff=1111111111111111111111111 10000001&11111111=000000000000000000000000 10000001 ,这个值就是129

所以最后显示的b的值为129

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 在RabbitMQ中实现Work queues工作队列模式

    在RabbitMQ中实现Work queues工作队列模式

    这篇文章主要介绍了如何在RabbitMQ中实现Work queues模式,代码详细,解释清晰,可以帮助大家更好理解java,对这方面感兴趣的朋友可以参考下
    2021-04-04
  • SpringCache快速使用及入门案例

    SpringCache快速使用及入门案例

    Spring Cache 是Spring 提供的一整套的缓存解决方案,它不是具体的缓存实现,本文主要介绍了SpringCache快速使用及入门案例,感兴趣的可以了解一下
    2023-08-08
  • Spring整合Quartz实现定时任务调度的方法

    Spring整合Quartz实现定时任务调度的方法

    下面小编就为大家带来一篇Spring整合Quartz实现定时任务调度的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • Java IO文件编码转换实现代码

    Java IO文件编码转换实现代码

    这篇文章主要介绍了Java IO文件编码转换实现代码,有需要的朋友可以参考一下
    2013-12-12
  • 浅谈java分页三个类 PageBean ResponseUtil StringUtil

    浅谈java分页三个类 PageBean ResponseUtil StringUtil

    下面小编就为大家带来一篇浅谈java分页三个类 PageBean ResponseUtil StringUtil。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 图解Springboot集成七牛云并实现图片上传功能过程

    图解Springboot集成七牛云并实现图片上传功能过程

    在实际开发中 ,基本都会有应用到文件上传的场景,但随着或多或少的需求问题,之前有在springboot上用过七牛云实现图片上传,今天因为某些原因又重新使用了下七牛云因此想总结下七牛云
    2021-11-11
  • Java Socket实现的传输对象功能示例

    Java Socket实现的传输对象功能示例

    这篇文章主要介绍了Java Socket实现的传输对象功能,结合具体实例形式分析了java socket传输对象的原理及接口、客户端、服务器端相关实现技巧,需要的朋友可以参考下
    2017-06-06
  • Spring详细讲解事务失效的场景

    Spring详细讲解事务失效的场景

    实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制,好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,下面这篇文章主要给大家介绍了关于Spring事务失效场景的相关资料,需要的朋友可以参考下
    2022-07-07
  • Java使用JDBC实现Oracle用户认证的方法详解

    Java使用JDBC实现Oracle用户认证的方法详解

    这篇文章主要介绍了Java使用JDBC实现Oracle用户认证的方法,结合实例形式分析了java使用jdbc实现数据库连接、建表、添加用户、用户认证等操作流程与相关注意事项,需要的朋友可以参考下
    2017-08-08
  • SpringCloud Config统一配置中心问题分析解决与客户端动态刷新实现

    SpringCloud Config统一配置中心问题分析解决与客户端动态刷新实现

    springcloud config是一个解决分布式系统的配置管理方案。它包含了 client和server两个部分,server端提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client端通过接口获取数据、并依据此数据初始化自己的应用
    2022-10-10

最新评论