java中int与byte、long与byte之间的互相转换

因为转换会用到运算符和补码的知识,下面先对运算符的使用做个简单的介绍。

与(&)、非(~)、或(|)、异或(^)简介

1.与运算符
与运算符用符号“&”表示,其使用规律如下:
两个操作数中位都为1,结果才为1,否则结果为0,例如下面的程序段。

    public static void main(String[] args) {
        int a = 129;
        int b = 128;
        System.out.println("a 和b 与的结果是:" + (a & b));
    }

运行结果
a 和b 与的结果是:128
下面分析这个程序:
“a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。

2.或运算符
或运算符用符号“|”表示,其运算规律如下:
两个位只要有一个为1,那么结果就是1,否则就为0,下面看一个简单的例子。

    public static void main(String[] args) {
        int a = 129;
        int b = 128;
        System.out.println("a 和b 或的结果是:" + (a | b));
    }

运行结果
a 和b 或的结果是:129
下面分析这个程序段:
a 的值是129,转换成二进制就是10000001,而b 的值是128,转换成二进制就是10000000,根据或运算符的运算规律,只有两个位有一个是1,结果才是1,可以知道结果就是10000001,即129。

3.非运算符
非运算符用符号“~”表示,其运算规律如下:
如果位为0,结果是1,如果位为1,结果是0,下面看一个简单例子。

    public static void main(String[] args) {
        int a = 2;
        System.out.println("a 非的结果是:" + (~a));
    }

运行结果
a 非的结果是:-3

4.异或运算符
异或运算符是用符号“^”表示的,其运算规律是:
两个操作数的位中,相同则结果为0,不同则结果为1。下面看一个简单的例子。

    public static void main(String[] args) {
        int a = 15;
        int b = 2;
        System.out.println("a 与 b 异或的结果是:" + (a ^ b));
    }

运行结果
a 与 b 异或的结果是:13
分析上面的程序段:a 的值是15,转换成二进制为1111,而b 的值是2,转换成二进制为0010,根据异或的运算规律,可以得出其结果为1101 即13。

补码反码介绍

1.原码:
一个byte是一个字节,一个字节是由8个位组成。其中最高位是符号位,范围就是127 ~ -128。

即:0111 1111~1111 1111

也就是说:0000 0001 代表的是1,

1000 0000 代表的是-128。
反码
正数的反码是其本身(正数的符号位是0);

负数的反码是:在原码的基础上,符号位不变,其他位取反。(负数的符号位是1)

即:-128的原码是:1000 0000

反码是:1111 1111

补码
补码是在原码的基础上,符号位不变,其他位取反+1。

例如: 1的原码是:0000 0001
反码是:0000 0001

符号位不变,取反: 0111 1111

+1(逢二进一)
补码是:1111 1111

下面开始上正菜

以int和byte互转为例进行分析

    public static void main(String[] args) {
        int a = 129;
        // 第一组 第二组 第三组 第四组
        // 2的二进制表示完整为 "[00000000][00000000][00000000][00000010]"[]括号实际没有,为了看起来清楚加的
        byte[] b = new byte[4];
        // 向右移位是 低位舍弃,高位补符号位
        // 向右移位运算,移动24位后,高8位,被移动到低8位上,二、三、四组都会被丢弃
        b[0] = (byte) (a >> 24);
        // 向右移动16位,高16位到低16位地方,第三、四组会被舍弃,至于&0xff这里不容易看出来,b[3]那一行能看出来
        b[1] = (byte) ((a >> 16) & 0xff);
        // 移动8位第四组会被丢弃,结果还是0
        b[2] = (byte) ((a >> 8) & 0xff);
        // 不移动直接进行与(&)运算,0xff的二进制是第四位为8个1 其他是0的数,作用就是排除不想要的位
        // 这里来个例子 [00000000][00000100][00000100][00000010]假如有这么个二进制的数字
        // 如果你想取到[00000100]字节的值 , 先对其向右移动8位变为
        // [00000000][00000000][00000100][00000100]
        // 然后和0xff与运算,0xff二进制[00000000][00000000][00000000][11111111]
        // 与运算后的结果就为[00000000][00000000][00000000][00000100]
        // 这样需要的字节就拿到了
        b[3] = (byte) (a & 0xff);
        for (byte c : b) {
            System.out.print(Integer.toBinaryString(c & 0xff) + " ");
        }
        System.out.println();
        // 把字节转回Int和上面颠倒下,就不多说了。
        int i = 0;
        i += ((b[0] & 0xff) << 24);
        i += ((b[1] & 0xff) << 16);
        i += ((b[2] & 0xff) << 8);
        i += ((b[3] & 0xff));
        System.out.println(i);
    }

问题:为什么要&0xff?

首先0xff是十六进制的255,也就是二进制的1111 1111,对0xff取与,实际上就是要取这个数最低八位的值,截一个字节的长度。

如果不用&0xff:

①计算机中是用补码的方式进行存储数据。

②如果不用&0xff,那么在进行负数的运算时就会出现问题,如:使用-1进行运算,-1的byte补码是:1111 1111,对应的十六进制数字是0xff;

                       -1的int补码(32位)是1111 1111 1111 1111 1111 1111,如果将byte转换为int,那么对应的十六进制数是0xffff。

结果不正确(对于负数而言)。

所以为了计算结果的正确性,我们就要对字节进行&0xff操作。

算法实现

public class Utilities {
    
    public static byte[] int2Bytes(int num) {
        byte[] byteNum = new byte[4];
        for (int ix = 0; ix < 4; ++ix) {
            int offset = 32 - (ix + 1) * 8;
            byteNum[ix] = (byte) ((num >> offset) & 0xff);
        }
        return byteNum;
    }

    public static int bytes2Int(byte[] byteNum) {
        int num = 0;
        for (int ix = 0; ix < 4; ++ix) {
            num <<= 8;
            num |= (byteNum[ix] & 0xff);
        }
        return num;
    }

    public static byte int2OneByte(int num) {
        return (byte) (num & 0x000000ff);
    }

    public static int oneByte2Int(byte byteNum) {
        return byteNum > 0 ? byteNum : (128 + (128 + byteNum));
    }

    public static byte[] long2Bytes(long num) {
        byte[] byteNum = new byte[8];
        for (int ix = 0; ix < 8; ++ix) {
            int offset = 64 - (ix + 1) * 8;
            byteNum[ix] = (byte) ((num >> offset) & 0xff);
        }
        return byteNum;
    }

    public static long bytes2Long(byte[] byteNum) {
        long num = 0;
        for (int ix = 0; ix < 8; ++ix) {
            num <<= 8;
            num |= (byteNum[ix] & 0xff);
        }
        return num;
    }

    public static void main(String[] args) {
        int num = 129;
        System.out.println("测试的int值为:" + num);

        byte[] int2bytes = Utilities.int2Bytes(num);
        System.out.printf("int转成bytes: ");
        for (int i = 0; i < 4; ++i) {
            System.out.print(int2bytes[i] + " ");
        }
        System.out.println();

        int bytes2int = Utilities.bytes2Int(int2bytes);
        System.out.println("bytes转行成int: " + bytes2int);

        byte int2OneByte = Utilities.int2OneByte(num);
        System.out.println("int转行成one byte: " + int2OneByte);

        int oneByte2Int = Utilities.oneByte2Int(int2OneByte);
        System.out.println("one byte转行成int: " + oneByte2Int);
        System.out.println();

        long longNum = 100000;
        System.out.println("测试的long值为:" + longNum);

        byte[] long2Bytes = Utilities.long2Bytes(longNum);
        System.out.printf("long转行成bytes: ");
        for (int ix = 0; ix < long2Bytes.length; ++ix) {
            System.out.print(long2Bytes[ix] + " ");
        }
        System.out.println();

        long bytes2Long = Utilities.bytes2Long(long2Bytes);
        System.out.println("bytes转行成long: " + bytes2Long);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

  • 1、与运算符的理解(&): 参加运算的两个数据,按二进位进行“与”运算。如果两个相应的二进位都为1,则该位的结果值...
    黄海佳阅读 5,797评论 0 1
  • 「WTF系列」深入Java中的位操作 关于WTF系列 引 学完本章节你将学会位的基础概念与语法,并且还会一些骚操作...
    qiujuer阅读 867评论 0 5
  • 进制基本概念 什么是进制?进制是一种计数的方式,数值的表示形式 常见的进制十进制、二进制、八进制、十六进制 进制书...
    极客江南阅读 1,992评论 0 11
  • 1、感恩老公早起做早餐,陪伴女儿的特殊时光。感恩老公下班后到家做晚饭,冬笋炒肉片。 2、感恩女儿及时打电话给我,告...
    芳华正茂阅读 377评论 0 1
  • 睿睿有点懒,之所以说有点是因为如果是她感兴趣的事,她就会不懒,比如说出去玩,每次都比我积极,早上不论几点只要一叫她...
    a晟睿阅读 593评论 1 3