[java] int转byte的细节

本文记录了一次Java面试经历,重点讨论了当int类型的255转换为byte类型时,为何结果会变为-1。通过深入理解Java中byte类型的范围、二进制补码表示法,解释了数值转换的原理,并提供手动计算和验证的方法。同时,文章揭示了在面试中遇到类似问题时的思考路径和解决策略。
摘要由CSDN通过智能技术生成

1.前言

本人两年Java开发经验,开发期间干的大都是CRUD的活,温水煮青蛙。最近就想着投投简历,看下外面是个啥行情,抽空也背了些八股文。上周面了一家,虽然问的内容都很基础,就是面那种刚毕业的大学生才会问的问题,结果太紧张,脑子一片空白,背的一些题都忘光了,被面试官吊起来打。。。。。

痛定思痛,从现在开始记录每一个面试官问到的题(如果还记得的话),冲!

2.问题

面试官:给你个int类型的255,把它赋值到byte类型的变量上,然后打印这个变量,结果是多少?

我:255吧

面试官:byte的范围是多少?

我:我想想(2分钟过去了)。。。。

面试官:好吧,我再换一个问题吧。。。。。。

其实面试前我还特地记了下各个基本类型占几个字节,然而上面问题都没答出来。

3.解答

话不多说,直接上代码:

public class TestCase {

    public static void main(String[] args) {
        int a = 255;
        byte b;
        b = (byte)a;
        System.out.println(b);

        System.out.println(Integer.toBinaryString(a));
        System.out.println(Byte.MIN_VALUE);
        System.out.println(Byte.MAX_VALUE);
    }

}

输出:

-1
11111111
-128
127

可以看到结果是 【-1】,但是这个结果是怎么来的呢?

3.1 技术准备

首先,回到一个比较基础的问题,java中byte的范围是多少?

从上面的打印结果中可以看到,byte类型的范围是[-128,127]。

那这个[-128~127]又是怎么来的呢?

这又涉及到java中的每种整数类型的占用的内存大小了。

java中byte类型的数占用1个字节。

一个字节=8位,一位就是一个0或1。

位又是啥概念?一位就是我们常说的1bit,1bit就是一个0或1,众所周知,计算机只认识0和1。

一位可以想象成一个小灯泡,灯泡亮了就是1,没亮就是0,一个字节就是8个小灯泡并排放在一起。

所以,一个byte类型的变量,大小为一个字节,就是用8位(8个小灯泡)来表示的。

那么这8位又是什么意思?怎么用8位来表示一个数?

首先要了解二进制的数怎么转化成十进制的数的,网上随便百度下都能找到,此处不再描述。

而java中,乃至计算机中实际上是如何用二进制来描述一个数的呢?

我们都是站在巨人的肩膀上的,怎么用8位表示一个数,几十年前的计算机先驱们都安排好了。答案是用了一个叫做【补码】的东西。补码又是啥??

不好解释,直接上链接:

原码,反码,补码的深入理解与原理_小小云麓的博客-CSDN博客_原码反码补码

3.2 开始计算

恶补了上面的内容后,首先就可以弄明白为什么byte的范围是[-128,127]了,然后终于可以开始研究为什么int的255转成byte后就变成了-1。

java中int是4个字节,就是4组小灯泡,每组8个灯泡。

int类型的255用二进制来表示(上面的演示程序中也打印出来的了,只是因为高位都是0所以就只打印了后面8个1)如下所示(左面为高位):

00000000 00000000 00000000 11111111

而byte只有1个字节,只能用1排小灯泡,int有4排,装不下,咋办呢?

所以就抛弃了高位的3个字节,把低位的那一排用来表示byte,如下图:

11111111

好了,现在只要我们把这8个1,翻译成人能方便地转化成熟悉的十进制数就行了。

翻译过程就是一个根据【补码】求【原码】的过程,如下:

首先要知道这是一个【补码】,先看第一位(符号位),第一位是 1,表示这是一个负数。

然后,既然是个负数,先不管第一位的1

        先反转(即0变1,1变0)后面7位,则后面7位反转后变成 7个0 :0000000

        然后将反转后的二进制数+1,就变成了6个0加一个1:0000001

所以加上之前的第一位的1,求得的原码就是【10000001】

即【-1】。

3.3 再次验证

好了,现在在随便找一个数,手工算一下,就找int类型的278吧

int类型的278的二进制补码表示:

public class TestCase {

    public static void main(String[] args) {
        int a = 278;
        byte b;
        b = (byte)a;
//        System.out.println(b);

        System.out.println(Integer.toBinaryString(a));
    }

}

输出:
100010110

即:
00000000 00000000 00000001 00010110

看后面8位:

00010110

首位是0,欸,是个正数,整数的【补码】和【原码】相同,那应该就是2 + 4 + 16 = 22

验证一下:

public class TestCase {

    public static void main(String[] args) {
        int a = 278;
        byte b;
        b = (byte)a;
        System.out.println(b);

        System.out.println(Integer.toBinaryString(a));
    }
}

输出:
22
100010110

果然,22,计算正确!

好,趁热打铁,再来一个,计算int类型的128,赋值给byte类型。

public class TestCase {

    public static void main(String[] args) {
        int a = 128;
        System.out.println(Integer.toBinaryString(a));
        byte b;
        b = (byte)a;
        System.out.println(b);
    }
}

输出:
10000000
-128

首先看下int的二进制表示:

00000000 00000000 00000000 10000000

 转化成byte的二进制:

10000000

欸,先看首位,是个1,是个负数,

反转后面7个0,变成7个1,7个1在加1,就变成了一个1跟7个0:

1111111 + 0000001 = 10000000

在结合首位的1,得到的原码就是:

110000000

即-1 乘 2的7次方 = -128

好,再来一个负数的int,计算int类型的-130,赋值给byte类型。

public class TestCase {

    public static void main(String[] args) {
        int a = -130;
        System.out.println(Integer.toBinaryString(a));
        byte b;
        b = (byte)a;
        System.out.println(b);
    }
}
输出:
11111111111111111111111101111110
126

int的二进制: 

11111111 11111111 11111111 01111110

 byte的二进制:

01111110

首先,首位是个0,是个正数,也不用取反了,直接按位加就完了,2+4+8+16+32+64 =  126

所以就是126

4.简单求法

讲道理,手工从二进制算十进制还好。从十进制手工算二进制,你是在刁难我胖虎!

其实,byte的范围之内部分,int与之都是对应的,一旦int的值超过了byte的范围,那么就从byte的另一个边界开始轮回就可以了:

128是第一个超过byte最大值的数,那么就从byte的最小值开始数,即int的128转化为byte后就是-128,

同理int的129转成byte就是-127,后面依次类推。

往下数也是同样的道理,int的-128化为byte后就是-128,而int的-129化为byte后就是127。

所以这种大范围向小范围的数字兼容的,其实是有规律的,就拿int和byte来说,后8位总是一个循环的:

比如int的0:

int :00000000 00000000 00000000 00000000
byte:                           00000000

比如int的1:

int :00000000 00000000 00000000 00000001
byte:                           00000001

...

比如int的127:

int :00000000 00000000 00000000 01111111
byte:                           01111111

比如int的128:

int :00000000 00000000 00000000 10000000
byte:                           10000000  // -128

比如int的255:

 

int :00000000 00000000 00000000 11111111
byte:                           11111111 // -1

比如int的256:

int :00000000 00000000 00000001 00000000
byte:                           00000000  // 0

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值