今天,魏屌出了一道题,题目如下:

定义一个大头序的byte[]a={-1,-2,-3,-4},转换成short[]b.问b[0]和b[1]分别是多少?

乍一看,这题不难,无非就是移位操作,再进行组合。但是呢?对于用Java的童鞋来说,这里面有一个坑,稍不注意可能就踩进去了。在说之前,我先把代码和答案贴出来吧。

看到这里,可能有的童鞋比较奇怪,为啥要&0xff,这不相当于没变化吗?非也,不信我举个例子。

答案是-127和129。很奇怪不是吗?我想的明明都是-127啊!!!

解答这个问题之前,我们先注意一下,b1的类型是int,而不是byte,这是因为byte的任何计算操作之后,都默认转成int,先明确这个概念。

然后,重头戏来了,大学计算机组成原理我们都学过原码,反码和补码,概念问题这里就不说了,也不用想书本上那些定义,学以致用嘛,一张图说明问题。

是不是很easy?这里再强调一个问题,就是Java中只有有符号数!Java中只有有符号数!Java中只有有符号数!重要的事情说三遍!

那么好了,Java中的数值存储就像这个大圆盘!

我们接着看为什么输出129?已知byte经过计算之后会变成int,但是人家int是32位的啊,byte才8位,所以只能补位啦,诶呀,问题来啦,怎么补位呢?这也是今天想强调的哦!

b是byte类型,其计算机存储的补码是10000001(8位)。

转成int后,Java中的扩展方式是补符号位扩展,何谓补符号位扩展?就是变成了11111111 11111111 11111111 10000001(32位),为啥要这样变?因为这样变还是-127,数值大小没有变!

而我们如果&0xff呢? b&0xff=11111111 11111111 11111111 10000001&11111111=00000000 00000000 00000000 10000001,这个值就是129,这就是补零扩展啦!所以129的问题解决啦!

什么?你问补零扩展有什么用?我们回到魏屌的那道题,两个byte合成一个short,short可是16位哦,如果我们不&0xff,即写成

s[1] = (short)((bs[2] << 8) | bs[3]);

输出结果发现变成了-4。为什么呢?

还是刚才那个思路啊,bs[2]是-3,即11111101,bs[3]是-4,即11111100,

(bs[2] << 8)就变成了11111111 11111111 11111101 00000000,

((bs[2] << 8) | bs[3])就变成了11111111 11111111 11111101 00000000 | 11111111 11111111 11111111 11111100 = 11111111 11111111 11111111 11111100,

再转成short,就是11111111 11111100,结果就是-4啦!就酱紫!

所以Java中byte和short互相转换的代码应该是:

// short转byte
short x = -32752;//定义一个short
byte high = (byte) (0xFF & (x>>8));//定义第一个byte
byte low = (byte) (0xFF & x);//定义第二个byte
System.out.println(high);//打印第一个byte值
System.out.println(low);//打印第二个byte值
// byte转short
short z = (short)(((high & 0xFF) << 8) | (0xFF & low));
System.out.println(z);//输出的结果就是-32752

最后总结一下:

因为Java中只有有符号数,当byte扩展到short, int时,即正数都一样,因为符号位是0,所以无论如何都是补零扩展;但负数补零扩展和按符号位扩展结果完全不同。

补符号数,原数值不变。

补零时,相当于把有符号数看成无符号数,比如-127 = 0x81,看成无符号数就是129, 256 + (- 127)。

对于有符号数,从小扩展大时,需要用&0xff这样方式来确保是按补零扩展。

而从大向小处理,符号位自动无效,所以不用处理。

浅谈Java中的补零扩展和补符号位扩展的更多相关文章

  1. 浅谈Java中接口与抽象类的异同

    浅谈Java中接口与抽象类的异同 抽象类和接口这两个概念困扰了我许久,在我看来,接口与抽象类真的十分相似.期间也曾找过许许多多的资料,参考了各路大神的见解,也只能是简简单单地在语法上懂得两者的区别.硬 ...

  2. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  5. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  6. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  7. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

  8. 浅谈Java中的final关键字

    浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. 【转】浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

随机推荐

  1. 常用class 总结

    清除浮动 // Clearfix @mixin clearfix { &:before, &:after { content: " "; // 1 display: ...

  2. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何声明定时器,使用定时器TON模块 TC3

    TON功能块功能: 当输入为高电平时,计时器开始计时,CV表示计时器计时的当前值,而PV则是计时的目标值,当CV的值等于PV的值时,输出置1.     在主程序接下去的地方按下F2并添加TON功能块. ...

  3. ionic搜索头部

    <div class="item-input-inset bar"> <form action="javascript:;" style=&q ...

  4. 常见Style 对象属性值

    Style对象的主要需要关注的属性分为4类,下面分别介绍下: Background 属性 backgroundColor 属性设置元素的背景颜色 Object.style.backgroundColo ...

  5. webSQL 实现即时通讯

    websql存储方式一共有以下几个方法 openDatabase:这个方法使用现有的数据库或新建数据库来创建数据库对象. transaction:这个方法允许我们执行事务处理; executeSql: ...

  6. Android设计模式(八)--模板方法模式

    到国美面试Android的时候.问我的设计模式相关的问题: 1.单例模式的意义时什么. 2.有哪几种工厂方法模式: 3.你用过的模板方法模式.举例说明: 自己感觉答的一塌糊涂. 模板方法模式都没说出来 ...

  7. struts2 常用标签

    版权声明:本文为博主原创文章,未经博主允许不得转载. Struts2可以将所有标签分成3类: 准备工作:需要在JSP页面引入标签库 <%@ taglib prefix="s" ...

  8. Swift的数组与OC中数组的区别

    相同的值可以多次出现在一个数组的不同位置: Swift中的数组,数据值在被存储进入到某个数组之前类型必须明确,可以显示的类型标注或者类型推断.而且,Swift中的数组不必是对象类型. OC中的NSAr ...

  9. Idea golang "can’t find import" 解决方法

    如题,在使用leveldb go wrapper levigo 的时候,本地安装好levigo后,通过命令行编译代码正常并能work,但在Idea中使用时出现: can't find import & ...

  10. linux 重启网卡的方法

    http://blog.163.com/drzxqing@126/blog/static/59351445201052392516841/