java 类型转换的原理

Wesley13
• 阅读 649

最近在看JDK的源码,在看源码的时候看到了0xff这么个东东,从这里引出了类型转换。因此在此记录下。

在写原理之前先看几个例子。byte b=-1;int a=b;然后打印a得出的结果是-1.int b=-1;byte a=(byte)b;打印a得出来的是-1。int a=255;byte b=(byte)255;打印b得出的结果也是-1;而把这个强制转出来的-1再转回int,得出的确不是255了,有点奇怪了。这是为什么那?好了,废话不过说,下面就开始讨论为什么了。在讲这个之前先来几个概念。二进制中的原码,反码,补码,补位,真值。再有就是byte类型和int类型分别占了多少位。这里需要说一下,二进制的高位是符号位,1表示负数,0表示正数。注:java是用补码存储数据的。

byte类型占一个字节,一个字节由8位二进制组成,所以说byte类型占了8位。int类型占4个字节,所以说int类型占了8位。

真值:这个就看字面意思,int a=-1;a的真值就是-1.

原码:int类型的-1的二进制表示,由于-1是负数,又是int类型的,所以他需要32个二进制来表示,二进制的最高位是符号位,所以为1,1的二进制为1,所以-1的二进制表示为   1000 0000 0000 0000 0000 0000 0000 0001;

反码:正数的反码就是原码,负数的反码是在原码的基础上,符号位不变,其余位取反。所以int类型的-1的反码是

1111 1111 1111 1111 1111 1111 1111 1111。

补码:正数的补码就是原码,负数的补码是在反码的基础上加1。所以,int类型的-1的补码是 1111 1111 1111 1111 1111 1111 1111 1111。

补位:补位是二进制中在扩充位数的时候,位数不够需要在左边补齐,补齐的方式为如果是正数的补位,左边全部补0,负数左边全部补1(也就是说补位的时候补足的是符号位)。

进入正题:

int a=-1;byte b=(byte)a;b的结果是-1。为什么int类型给byte类型赋值的时候为什么需要做强制类型转换,因为int类型是32位的,而byte类型只有8位,8位无法存储32位,所以需要把32位强制转为8位。这个结果是怎么得出来的呢?从二进制的角度开始分析,int类型的-1的补码是 1111 1111 1111 1111 1111 1111 1111 1111。他在强制转为8位byte的时候需要把高24位丢弃,只保留8位,也就是 1111 1111 ,这8位是补码的形式,转化为原码,8位的最高位是1.所以是负数。根据原码,反码和补码的计算方法可以得出他的反码是1111 1110 ,原码是 1000 0001 ,所以他的真值是-1。

byte a =-1,int b=a,b的结果是-1。为什么byte类型给int类型赋值的时候不需要做强制类型转换,因为是从低位向高位转,会自动补位。byte类型的-1的原码是1000 0001 ,他的补码就是1111 1111 。由于byte类型需要从8位转为32位的int类型,位数不够,根据扩充原则需要在二进制原码的左边扩充符号位。注意,byte类型的-1的原码的补位后的结果不是1111 1111 1111 1111 1111 1111 1000 0001 ,而是1000 0000 0000 0000 0000 0000 0000 0001 。原因是在补位的时候是先将真值取绝对值,计算出他的原码,将原码扩充完毕之后,最高位改为符号。因此,byte类型的-1的绝对值是1,他的原码是0000 0001 ,补全32位需要在左边补24个0,补完之后由于是负数的补位,所以将最高位的符号位改为1,表示负数,所以byte类型的-1扩充为int类型后他的原码是1000 0000 0000 0000 0000 0000 0000 0001 。(其实根据补码补位也是可以的,byte 类型-1 的补码是1111 1111 ,他补位之后,因为最高位是负数,所以左边全部补充1 ,为1111 1111 1111 1111 1111 1111 1111  1111 ,这是补码,最高位符号位不变,他的反码是1111 1111 1111 1111 1111 1111 1111  1110,原码就是 1000 0000 0000 0000 0000 0000 0000 0001 )所以,他的真值就是-1了。

再看最后一个例子,int a=255;byte b=(byte)a;b的值为什么是-1那?int类型的255的原码是0000 0000 0000 0000 0000 0000 1111 1111,反码是0000 0000 0000 0000 0000 0000 1111 1111,补码是0000 0000 0000 0000 0000 0000 1111 1111。32位转8位需要丢掉高24位,剩下1111 1111八位。剩下的八位的最高位是符号位,将他转为原码就是1000 0001,真值就是-1了。

大家在自己算一下(byte)234的结果是什么,然后在IDE里在运行下看和自己手写算出来的一样吗。

语文水平不太好,写的可能有点啰嗦,希望你能理解下,写这篇文章就是想和大家分享下在学习当中遇到的问题,怎么解决的,学习java不是学习下框架什么的就可以了,只有了解底层的原理,在看别人写的代码才能真正理解。才能真正学会java,而不是感到迷茫。在此要感谢我亲爱的媳妇,前面那些都是她帮我打字的,这么晚了还要让她陪我熬夜,好感动!

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这