byte b = -127;
System.out.println(b); // -127
int b1 = b & 0xff;
System.out.println(b1); // 129

b的二进制表示为:10000001

(1)符号位扩展:

11111111 11111111 11111111 10000001 = -127

(2)补零扩展:

b&0xff为
11111111 11111111 11111111 10000001
              &   11111111
                 -----------
00000000 00000000 00000000 10000001 = 129

转型被用来将一个数值从一种类型转换到另一种类型。 下面的程序连续使用了三个转型。那么它到底会打印出什么呢?

public class Multicast{
   public static void main (String[] args){
        System.out.println((int)(char)(byte) -1);
   }
}

无论你怎样分析这个程序,都会感到很迷惑。它以 int 数值-1 开始,然后从 int转型为 byte,之后转型为 char,最后转型回 int。第一个转型将数值从 32 位窄化到了 8 位,第二个转型将数值从 8 位拓宽到了 16 位,最后一个转型又将数值从 16 位拓宽回了 32 位。这个数值最终是回到了起点吗?如果你运行该程序,你就会发现不是。它打印出来的是 65535,但是这是为什么呢?

该程序的行为紧密依赖于转型的符号扩展行为。Java 使用了基于 2 的补码的二进制运算,因此 int 类型的数值-1 的所有 32 位都是置位的。从 int 到 byte 的
转型是很简单的,它执行了一个窄化原始类型转化(narrowing primitive conversion),直接将除低 8 位之外的所有位全部砍掉。这样做留下的是一个 8
位都被置位了的 byte,它仍旧表示-1。
从 byte 到 char 的转型稍微麻烦一点,因为 byte 是一个有符号类型,而 char是一个无符号类型。在将一个整数类型转换成另一个宽度更宽的整数类型时,通
常是可以保持其数值的,但是却不可能将一个负的 byte 数值表示成一个 char。因此,从 byte 到 char 的转换被认为不是一个拓宽原始类型的转换,而是一个拓
宽并窄化原始类型的转换(widening and narrowing primitive conversion):byte 被转换成了 int,而这个 int 又被转换成了 char。所有这些听起来有点复杂,幸运的是,有一条很简单的规则能够描述从较窄的整型转换成较宽的整型时的符号扩展行为:如果最初的数值类型是有符号的,那么就执行符号扩展;如果它是 char,那么不管它将要被转换成什么类型,都执行零扩展。了解这条规则可以使我们很容易地解决这个谜题。
因为 byte 是一个有符号的类型,所以在将 byte 数值-1 转换成 char 时,会发生符号扩展。作为结果的 char 数值的 16 个位就都被置位了,因此它等于 216-1,即 65535。从 char 到 int 的转型也是一个拓宽原始类型转换,所以这条规则告诉我们, 它将执行零扩展而不是符号扩展。 作为结果的 int 数值也就成了 65535,
这正是程序打印出的结果。尽管这条简单的规则描述了在有符号和无符号整型之间进行拓宽原始类型时的符号扩展行为,你最好还是不要编写出依赖于它的程序。如果你正在执行一个转型到 char 或从 char 转型的拓宽原始类型转换,并且这个 char 是仅有的无符号整型,那么你最好将你的意图明确地表达出来。如果你在将一个 char 数值 c 转型为一个宽度更宽的类型,并且你不希望有符号扩展,那么为清晰表达意图,可以考虑使用一个位掩码,即使它并不是必需的:
int i = c & 0xffff;
或者,书写一句注释来描述转换的行为:
int i = c; //不会执行符号扩展
如果你在将一个 char 数值 c 转型为一个宽度更宽的整型,并且你希望有符号扩展,那么就先将 char 转型为一个 short,它与 char 具有同样的宽度,但是它是
有符号的。在给出了这种细微的代码之后,你应该也为它书写一句注释:
int i = (short) c; //转型将引起符号扩展
如果你在将一个 byte 数值 b 转型为一个 char,并且你不希望有符号扩展,那么你必须使用一个位掩码来限制它。这是一种通用做法,所以不需要任何注释:
char c = (char) (b & 0xff);
这个教训很简单:如果你通过观察不能确定程序将要做什么,那么它做的就很有可能不是你想要的。要为明白清晰地表达你的意图而努力。尽管有这么一条简单的规则,描述了涉及有符号和无符号整型拓宽转换的符号扩展行为,但是大多数程序员都不知道它。 如果你的程序依赖于它, 那么你就应该把你的意图表达清楚。

参考:

(1)https://www.cnblogs.com/DarrenChan/p/6838771.html

(2)https://www.cnblogs.com/liujinhong/p/6005714.html

Java的符号扩展与零扩展的更多相关文章

  1. C++ 中注意,零扩展和符号位扩展

    版权声明:本文为博主原创文章,未经博主允许不得转载. 首先,介绍一下两种扩展的定义 转 http://blog.csdn.net/jaylong35/article/details/6160736 符 ...

  2. java中符号类型和无符号类型的问题分析

    一 参考博文 java中无符号类型的解决方案 二 java中的无符号数和有符号数 在计算机中,可以区分正负的类型,称为有符号类型,无正负的类型,称为无符号类型. 使用二进制中的最高位表示正负 计算机中 ...

  3. 浅谈Java中的补零扩展和补符号位扩展

    今天,魏屌出了一道题,题目如下: 定义一个大头序的byte[]a={-1,-2,-3,-4},转换成short[]b.问b[0]和b[1]分别是多少? 乍一看,这题不难,无非就是移位操作,再进行组合. ...

  4. C语言的有符号与无符号,二进制整数的扩展与截断

    C语言的有符号与无符号,二进制整数的扩展与截断 前一节说了整数的表示方式,,也就是无符号编码与补码编码.这一届说一下二进制整数的扩展与截断,这部分内容与C语言挂钩.so,我们先看下面C语言的有符号和无 ...

  5. Java 动态代理机制分析及扩展

    Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...

  6. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  7. Java 动态代理机制分析及扩展,第 1 部分

    Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...

  8. 在 Windows Azure 网站中进行纵向扩展和横向扩展

    编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Byron Tardif 撰写. 当您开始一个新的 Web 项目,或者刚刚开始开发一般的网站和应用程序时,您可能希望从小处着手. ...

  9. Memcache服务器端+Redis服务器端+PHP Memcache扩展+PHP Memcached扩展+PHP Redis扩展+MemAdmin Memcache管理工具+一些概念(更新中)

    Memcache和Redis因为操作简单,是我们常用的服务器数据缓存系统,以下文字仅作备忘记录,部份转载至网络. 一.定义 1.Memcache Memcache是一个高性能的分布式的内存对象缓存系统 ...

随机推荐

  1. 1) Apache Maven 's README.txt

    Apache Maven What is it? ----------- Maven is a software project management and comprehension tool. ...

  2. git-fork其他人的代码

    1. 2. 3.然后在本地创建目录      第一步:mkdir test      第二步:cd test      第三步:git init(初始化)      第五步:git remote ad ...

  3. HDU6023 Automatic Judge 2017-05-07 18:30 73人阅读 评论(0) 收藏

    Automatic Judge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  4. JAVA实现WC.exe功能

    项目要求 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功能,并能够快速地处理多个文件. 具体功能要求: 程序处理用户需求的模式为: wc.exe [paramet ...

  5. jvm 中的 ”永生代“

    “方法区” 主要存储的信息包括:常量信息,类信息,方法信息,而且是全局共享的(多线程共享): jvm 有多种实现方式(不同的厂商): 并不是所有的jvm 都有永生代的概念: 通常情况下, 很多人把 “ ...

  6. 论文笔记(2)-Dropout-Regularization of Neural Networks using DropConnect

    这篇paper使用DropConnect来规则化神经网络.dropconnect和dropout的区别如下图所示.dropout是随机吧隐含层的输出清空,而dropconnect是input unit ...

  7. Python学习-3.Python的模块加载

    Python中使用import关键字进行模块加载. 先在Visual Studio中建立PythonModuleLoad项目作为演示. 1.同目录加载 建立SameFolder.py文件 写入代码: ...

  8. 在ANTMINER(阉割版BeagleBone Black)运行Debain

    开门见山,直入主题 咸鱼入手3块阉割ARM板,经过快递近6天运输到手,不过价格便宜 东西下面这样的(借了咸鱼的图): 发现这块板是阉割版的国外beagleboard.org型号为BeagleBone ...

  9. 【cocos2d-x 3.0-Mac配置篇】

    就在昨天触控正式发布了3.0正式版本... 在这个喜大普奔的日子里,我们又开始了新一轮的革命,先不说其他的,再来看看3.0目录文件里面有什么? 首先是精简了很多,无论是从目录结构,和所用到的工具类,都 ...

  10. 用ndp部署storm应用

    本文由作者余宝虹授权网易云社区发布. 使用户ndp部署一个Java应用大家都非常熟悉的,但是看到某些同学用非常繁琐的方式部署storm应用的时候,我觉得很有必要整一个帮助教程,ndp帮助文档里面没有, ...