一篇文章搞懂Byte

1,143 阅读5分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

一篇文章搞懂Byte

一般和单片机打交道使用的是bytebyte是java中最小的单位了,极限优化,一个byte是8个bit,虽然bit只有0和1表示,但在编程的设计场景中已经可以表示很多东西了,比如错误和正确的状态,比如失败和成功的状态。那么在java中如何处理这些场景呢。

一、计算机的最小单位

讲这个问题之前,为了方便记忆,先讲一个由来。

据说世界上最简单的计算机是一个灯泡。

它可以通电、可以断电,通电就亮了,断电就灭了。

而在现代的计算机上只是让这种通电、断电的场景变得复杂。

通电相当于告诉它1,断电就相当于告诉它0。

通电和断电也可以被称作高电平低电平。

所以计算机中最小的单位的值就是0和1,0和1被称作位,也就是bit

二、Java语言中的最小单位

计算机中的最小单位是位(bit),那么在java中最小的单位是什么呢。

java中的基本数据类型有:

byte(字节) 8位

short(短整数) 16位

int(整数) 32位

long(长整数) 64位

float(单精度) 32位

double(双精度)64位

char(字符) 16位

boolean(布尔值)8位

除了8个基本数据类型之外,还有常用的String行勒,它是个一个比较特殊的存在,下次专门用一篇文章取理解它。

通过上诉,Java中最小的单位是byte

三、理解Byte类型

  • 在Java中Byte的特性
  1. 是最小的数据类型

  2. 值范围在[-128, 127],是带符号位signed byte

  • 理解signedbyte 概念。
  1. signed 表示有符号的,也就是有正负数的概念

  2. unsigned 表示无符号的,只有大小,也就是只有正数的概念

  • 什么是符号位?

对于signed带符号的表示来说,第一个bit位代表着正负,如果是0代表正数,如果位1,代表负数。比如十进制的1,对应二进制位0000 0001,第一个0为1,则为正1,也就是1

  • 为什么java中的取值范围是[-128, 127] ?

因为java采用带有符号位的表示方法。

三、Byte和bit的转化

既然一个byte 等于8个bit,那么java中又怎么获取byte中的bit呢?

3.1 从byte中取出8个bit

假设声明一个byte = 1,我们取出这个byte的8个位分别是多少。


// 声明

byte a = 1;

// 第一位

byte bit1 = (byte) ((a >> 7) & 1);

byte bit2 = (byte) ((a >> 6) & 1);

byte bit3 = (byte) ((a >> 5) & 1);

byte bit4 = (byte) ((a >> 4) & 1);

byte bit5 = (byte) ((a >> 3) & 1);

byte bit6 = (byte) ((a >> 2) & 1);

byte bit7 = (byte) ((a >> 1) & 1);

byte bit8 = (byte) ((a >> 0) & 1);

Log.d(TAG, "bit1:" + bit1); // 0

Log.d(TAG, "bit2:" + bit2); // 0

Log.d(TAG, "bit3:" + bit3); // 0

Log.d(TAG, "bit4:" + bit4); // 0

Log.d(TAG, "bit5:" + bit5); // 0

Log.d(TAG, "bit6:" + bit6); // 0

Log.d(TAG, "bit7:" + bit7); // 0

Log.d(TAG, "bit8:" + bit8); // 1

来分析下代码。

首先在程序员计算器中得到正确的值,分析它的结构。

对于Mac:计算器->显示->编程器

对于Windows:win+R -> 输入 calc 回车 -> 程序员计算器。

image.png

通过计算器可以得知,

十进制的1 对应的二进制的 0000 0001

那我们怎么把这些 0000 0001 分别取出来了。

原始数据 0000 0001

取第一位,就右移动7位,变成 0000 0000

然后&1,也就是&上 0000 0001

& 的含义是相同为1,不同为0

流程如图


0000 0001

>> 7

0000 0000

&

0000 0001

-----------------

0000 0001

结果为 1

3.2 将8个bit合成一个byte

那么如何将八个字节和成一个byte呢?


byte[] array = new byte[8];

array[0] = 0;

array[1] = 1;

array[2] = 1;

array[3] = 1;

array[4] = 0;

array[5] = 0;

array[6] = 1;

array[7] = 1;

byte temp = (byte) (array[0] << 7 | array[1] << 6 | array[2] << 5 | array[3] << 4 | array[4] << 3 | array[5] << 2 | array[6] << 1 | array[7]);

Log.d(TAG, "temp:" + temp); // 115

继续分析下代码。

原八个二进制 移位后

00000000 <<7 00000000

00000001 <<6 01000000

00000001 <<5 00100000

00000001 <<4 00010000

00000000 <<3 00000000

00000000 <<2 00000000

00000001 <<1 00000010

00000001 <<0 00000001

进行或 | 运算,有1为1,否则为0

二进制:01110011 十进制 115

四、Byte与Int的转换

先观察一个现象。


byte a = 127;

int b = (byte) -3;

int c = (byte) 255;

Log.d(TAG, "a & b & c:" + a + "&" + (b) + "&"+(c));

// a & b & c:127&-3&-1

由于讲过java中byte是有符号位的

所以在超过这个范围后就会变成负数

那么如果和无符号位的单片机(c语言)对接的呢。

那么就要用到位运算将无符号的位的数,转化成有符号位的数了。

只需要将这个数 &0xff 即可


byte a = 127;

int b = (byte) -3;

int c = (byte) 255;

Log.d(TAG, "a & b & c:" + a + "&" + (b & 0xff) + "&" + (c & 0xff));

// a & b & c:127&253&255

分析一下代码

0xff 使用0x开头表示,代表着16进制的数

那么16进制的0xff的二进制是多少呢

是 1111 1111

& 之后,保留原来的数据,但是转化成int,前面补上 3x8=24 个零,而第一位的零是符号位。

所以得到的都是正数了。