前言

本文由int转byte数组这样的题目代码引发的思考,其中涉及到多个让我混淆的地方。

直接上代码

  public byte[] toBytes(int number){byte[] bytes = new byte[4];bytes[3] = (byte)number;bytes[2] = (byte) ((number >> 8) & 0xFF);bytes[1] = (byte) ((number >> 16) & 0xFF);bytes[0] = (byte) ((number >> 24) & 0xFF);return bytes;}

如果对这段代码了然于胸,原理思路清洗,就可以不用阅读本文了。如果对这段代码的原理不是那么清晰,那么很可能是某个基础知识模糊遗忘了。
我们知道int强转成short,甚至char。但byte数组给人的感觉就是二进制的东西,好像和那些基本类型“不在一个维度上”,甚至想象不出转换出来是个什么效果,能打印出来吗。。。之所以会有这些疑问,因为我们对byte的一些基本概念混淆了,或许是从来没真正的理解透过。

一、先思考几个基础问题

问题一:byte是java基本类型吗,如果是,那它属于哪一类基本类型

问题二:byte是计算机中最小的单位吗,char呢? 能清晰的想出来java里8种基本类型的字节长度以及取值长度吗

问题三:我们知道java四个整数类型可以相互强转,比如,int转byte是怎么做的

问题四:如何理解程序中的& 0xFF是否必要,可否去掉

问题五:把int切成四个byte,放在byte[]里,顺序怎么摆放

问题六:我们应该学过“原码”、“反码”,“补码”,那么java的基础数值类型在计算机里是用的补码吗

以上这些问题先不要看答案,自己是否能很清晰的回答出来。


问题一答案

byte是java基本类型,而且是整数型(它不止可以用来表示二进制数据,还能表示数字哦)。
工作中我们会经常用byte数组,基本都是在涉及IO流传输数据相关代码中使用。也许就是用的场景太单一顺手了,byte给我们的感觉就是二级制的数据流,渐渐的就忽略了 这个类型居然和int之类 是一类东西,它的大小范围是-128~127,是不是好像在哪听过这个范围。是short吗,答案是否定的。这个范围还出现在Integer使用地址比较相等的时候,因为Integer会把-128-127范围内的数字放入常量池,我们可以直接使用==来比较是否相等。

问题二答案

byte 名字节,大该是因为他的英文名字听起来好像叫“比特”,和bit很像,然后又经常被用在数据流中,给人感觉就好像这是一个不可分割的最小单位。但实际上byte占8位,即 1byte = 8 bit。所以不是计算机中最小单位。
也许你在用数据库的时候,使用过bit这个数据类型,它只有true和false两个值(也就是1和0),这个单位我们可以称之为“位”,也就是我们所谓的最小单位。但不要和byte搞混了,他们之间差了8倍。 char就更大了,java中占两个字节,c语言中占一个字节。
8种基本类型字节数以及取值范围

类型 字节大小 取值范围
byte 1 -(2^7) ~ (2^7) - 1
short 2 -(2^15) ~ (2^15) - 1
int 4 -(2^31) ~ (2^31) - 1
long 8 -(2^63) ~ (2^63) - 1
char 2 -
boolean 4或1 true,false
float 4 6位有效数字
double 8 15位有效数字

在这张表里,你可能会对boolean这个类型产生疑问。对于本题答案,你甚至会想byte和boolean是不是有什么关联(你可能隐约感觉两者都是用来表示0和1的)。 当然这是完全错的,即使是bit和boolean也没什么联系,boolean在java中也不是只占1位。因为java中并没有规定boolean的表示方法,实际中boolean占了4字节(和int一样大),boolean[]中bolean元素则占1字节,所以上面表格里写4或1。

问题三答案

首先注意这里是说int强转成byte,而不是本文所说的int转byte[]。通过前一个问题我们知道int占32位,而byte占8位。比如int a10 = 261对应的二进制就是100000101【左边剩下的23个0就省略了】,想转成byte也很简单,就是直接截取最右边8位即可:00000101【十进制的5】,也就是261强转byte后等于5。

问题四答案

十六进制0xFF 也就是二进制的11111111, &运算的作用就是把两个二进制右边对齐,然后逐个&运算,只有两者都是1时结果才是1,
等效于截取右边8位二进制数。通过问题三,可知int强转byte就是简单截取右边8位,没有必要再& 0xFF。 所以上面的代码可以这么写

  public byte[] toBytes(int number){byte[] bytes = new byte[4];bytes[3] = (byte)number;bytes[2] = (byte) (number >> 8);bytes[1] = (byte) (number >> 16);bytes[0] = (byte) (number >> 24);return bytes;}

问题五答案

通过理解这段代码我们知道,int的32位二进制,最终被截断成4段,然后把这4段以byte的形式放入byte数组。如下所示

也许会有疑问,为什么不是这样

因为在二进制截取、排序的过程中 不要带入“意义”。也就是说,在排这些二进制段的时候不要想着这段二进制原本是什么意思(比如这里就不要想着这32位二进制是一个int数字),可以简单认为,这就是一串毫无意义字符串。而这串字符串就是从左往右读的,左边是开始,右边是结束。
另一个更准确的理解方式是:通过一个实际的例子画出图就能很容易看出

如果把00000101放在b0中,那么这个byte[]无论正着读还是反着读,二进制数字都是乱的。

问题六答案

首先给出答案:是的。 如果这个问题这么问:计算机中是使用原码还是补码表示数字,基本大家都会答:补码。这个问题之所以这么问,就是看概念是否清晰准确。如果关于补码的概念模糊的话,甚至可能会觉得补码应用于计算机内的所有信息,整数是不是用的补码反而不确定了。 下面就复习一下关于补码的知识:
上面说了,byte的取值范围是-128~127,这个范围我们应该不陌生,但为什么呢,为什么不是“两头对称”的呢,这就是补码造成的。
问题三答案,我们明白了int是如何转成byte的,例子大家应该也都能看明白。现在换一个例子int a = -216,二进制为1111111111111111111111111111111111111111111111111111111011111011,同样截取后8位,结果是11111011,表示十进制的-5。如果对这个计算过程以及结果有点意外,说明对补码认识不足。下面就以byte类型(8位二进制)为例,讲解一下补码 首先说一下概念及结论:

  1. java中的数字都是有符号的,即有正有负
  2. 有符号数字表示的二进制中左边第一位是符号位,0表示正数,1表示负数
  3. 原码:8位有符号的二级制的原始表达方式
  4. 反码:原码符号位不变,其他位取反(就是0变1,1变0)
  5. 补码:反码+1
  6. 计算机中的数字使用补码表示
  7. 使用规则: 正数的原码和补码一样(也就不存在反码),负数的反码根据上面的规则计算,即反码+1

为什么产生反码

  1. 原码中的 0000000【+0】 1000000【-0】
    有正0和负0,这两个本来一样的数却有两个不同的表示方式
  2. 原码的符号位不方便计算,而补码却能巧妙的把符号位带着一起做加法运算(这个就不细讲)。
    根据上面的规则,byte的256个数字对应关系如下
二进制表示 00000000 0000001 01111111
无符号十进制数字 0 1 127
补码十进制数字 0 1 127

10000000 1000001 11111111
128 129 255
-128 -127 -1

函数图如下

通过表格以及函数图,很明显看出byte的表示范围是-128 ~ 127【y轴。虽然画的是连续直线,其实是离散点】

二、总结

本程序简单讲就是:把32位的int像“切甘蔗”一样平均切成4段byte,从左至右依次放入byte[]。 前提是要理解byte、int等基本类型的本质,以及补码的作用及使用方式。懂了这些原理,不仅仅可以解决int转byte数组,反过来转换也是比较容易理解的。

int转byte数组以及相关原理相关推荐

  1. Int 转 byte 数组以及相关原理

    零.前言 本文由int转byte数组这样的题目代码引发的思考,其中涉及到多个让我混淆的地方. 直接上代码 public byte[] toBytes(int number){byte[] bytes ...

  2. java int byte数组_Java 中int与byte数组转换详解

    1.与运算符的理解(&): 参加运算的两个数据,按二进位进行"与"运算.如果两个相应的二进位都为1,则该位的结果值为1,否则为0.即 0&0=0:0&1=0 ...

  3. c++ byte数组转int, int转byte数组,byte数组转16进制字符串,16进制字符串转byte数组

    int转byte数组: void IntToBytes(int num, unsigned char* bytes, int size) {     for (int i = 0; i < si ...

  4. java byte转int原理_java中int与byte数组互转代码详细分析

    在java中,可能会遇到将int转成byte[]数组,或者将byte[]数组转成int的情况.下面我们来思考下怎么实现? 首先,分析int在java内存中的存储格式. 众所周知,int类型在内存中占4 ...

  5. java int转byte数组_javaint转byte数组

    JAVA中怎么将int数据转换为byte数据? 例如将int b=325转换为 byte a,结果为多少啊? JAVA中根据以下代码将int数据转换为byte数据: public static byt ...

  6. js整形int和byte数组互相转换

    //小端模式 function BytesToIntLittleEndian(bytes){var val = 0;for (var i = bytes.length - 1; i >= 0; ...

  7. java short to byte_java笔记 Java中byte数组与int,long,short,char间的转换

    package com.util; public class ByteUtil { /** * 转换short为byte * * @param b * @param s * 需要转换的short * ...

  8. java byte数组转long_Java中byte、byte数组与int、long的转换详解

    一.Java 中 byte 和 int 之间的转换源码: //byte 与 int 的相互转换 public static byte intToByte(int x) { return (byte) ...

  9. byte数组与int类型互相转换的几种方式

    查看原文:http://www.ibloger.net/article/147.html Java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中 ...

  10. Java数字类型转byte数组

    文章目录 方法1 自己写 int转byte数组 byte数组转int 参考:https://blog.csdn.net/qq_41054313/article/details/88424454 方法2 ...

最新文章

  1. Gartner:2020 年 AI 平台魔力象限:意外多多
  2. Vijos P1848 记数问题【进制】
  3. 文本比较算法Ⅲ——计算文本的相似度
  4. 关于开发自我训练课程
  5. VirtualBox安装linux mint教程
  6. leetcode 476. Number Complement | 476. 数字的补数(位运算)
  7. redisLock redis分布式锁
  8. quartus编译出现的问题
  9. oracle esb 灾备,两地三中心双活系统灾备切换场景和数据补录问题?
  10. MapXtreme 随笔记录1
  11. 【课程·研】高级人工智能 | MOOC习题及课后作业:期末考试
  12. 浅谈LSTM对于周期时间序列数据的预测
  13. 跳转到app下载页面和app评论页面
  14. java转码及页面乱码原因分析
  15. 我如何从月薪8K到25K?现在分享给大家自己的经历
  16. 目标检测--RFBNet训练自己制作数据集出现loss=nan问题的解决方法
  17. Rust实战系列-基本语法
  18. springboot社工服务中心管理信息系统 毕业设计-附源码021009
  19. 2022 CCF中国开源大会—开放原子开源创新发展论坛顺利举办!
  20. Unity 使用一张贴图来控制材质主贴图的透明度

热门文章

  1. 电脑字体变成繁体中文怎么更改过来呢
  2. 寻找成功人生的方向-在新东方听讲座的感悟
  3. 因子分解机(FM) +场感知分解机 (FFM) 入门
  4. STM32+GM65二维码识别模块
  5. 爱普生xp245手动清零_仍在Windows XP上吗? 手动更新或感到烦恼
  6. 联想笔记本驱动升级,指纹识别不了不成功解决方法
  7. google退出中国声明 英文版原文
  8. Kali Linux 暴力破解 Excel密码
  9. 浪曦云团的博客正式入驻CSDN
  10. 卷积神经网络(CNN)原理详解