Java byte位移操作 注意事项

Java对byte 的 + - * / >> >>> << & | ^ (加,减,乘,除,右移,左移,无符号右移,位与,位或,位异或)操作,均会是首先将byte转化为int, 再行运算。这一事实可能导致多种问题:

假设我们想进行如下byte运算: 1111 1000 右移1位,再与0000 0001 或运算,得 0111 1101。

直觉写程序如下:

byte b = 0xf8;

byte b2 =  b >> 1 | 0x01;

这个写法里有多重错误,现逐个纠正:

1 编译器报错,int无法直接自动转化为byte

为解决此问题,加强制转化。

byte b = (byte)0xf8;

byte b2 = (byte)( (b >> 1) | 0x01);

2 输出为 1111 1101 不是我们想要的 0011 1101

原因是>> 是有符号右移,当符号位为1时,左侧补的是1而非0。

修改为使用 >>> 无符号右移:

byte b = (byte)0xf8;

byte b2 = (byte)( (b >>> 1) | 0x01);

3 运行后发现输出依然为 1111 1101

原因是byte在运算前先转化为int再行位运算,因此分解后的运算步骤如下:

b 转化为int  1111 1000 转化为      11111111 11111111 11111111 11111000

无符号右移1位                      01111111 11111111 11111111 11111100

与 0x01 按位或                  01111111 11111111 11111111 11111101

强制转化回byte     11111101

解决方案,在右移运算前先 位与 0xff

byte b = (byte)0xf8;

byte b2 = (byte)( ((b & 0xff )>>> 1) | 0x01);  //注意必须加括号,因为 >>> 的优先级高于 &

4 运行后发现输出为我们想要的结果  0111 1101。运算步骤分解如下:

b 转化为int  1111 1000 转化为   11111111 11111111 11111111 11111000

和0xff 进行 & 操作              00000000 00000000 00000000 11111000

无符号右移1位   00000000 00000000 00000000 01111100

与 0x01 按位或  00000000 00000000 00000000 01111101

强制转化回byte  01111101

5 关于System.out.println();

byte b = (byte)0xf8;

System.out.println(b);   --最终输出为-8

运算步骤为:

b 转化为int  1111 1000 转化为   11111111 11111111 11111111 11111000

取符号位 -                      -1111111 11111111 11111111 11111000

取返+1(因为是按补码运算)      -0000000 00000000 00000000 00001000

输出  -8

最终结论:

1 区分使用 >> 和 >>>

2 在 >> 操作前要首先 & 0xff

3 注意符号优先级,正确使用括号。

4 需要强烈注意的一点是 & 的优先级小于 + . 因此 a = b & 0xff + 2000 的结果 可能不是你想要的

附:

打印byte,int 每个bit值的函数。

public static void printByte(byte b){

for(int i = 7; i >=0 ; i --){

int shiftleft = (b >> i) & 0x01;

System.out.print(shiftleft);

}

System.out.println();

}

public static void printInt(int b){

for(int i = 31; i >=0 ; i --){

int shiftleft = (b >> i) & 0x01;

System.out.print(shiftleft);

}

System.out.println();

}

时间: 2024-08-10 19:09:12

Java byte位移操作 注意事项的相关文章

Java Spring mvc 操作 Redis 及 Redis 集群

本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html 关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用 Redis 是什么,能做什么 Redis 是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.它支持字符串.哈希表.列表.集合.有序集合,位图,hyperloglogs等数据类型.内置复制.Lua脚本.LRU收回.事务以及不同级别磁盘持久化功能,同时通过Redis

java byte【】数组与文件读写(增加新功能)

今天在测试直接写的文章: java byte[]数组与文件读写 时,想调用FileHelper类对字节数组以追加的方式写文件,结果无论怎样竟然数据录入不全,重新看了下文件的追加模式,提供了两种方式: 方式一: 字节数组写入文件(不追加) //将byte数组写入文件 public void createFile(String path, byte[] content) throws IOException { FileOutputStream fos = new FileOutputStream(

Java 基本IO操作

1.基本IO操作     有时候我们编写的程序除了自身会定义一些数据信息外,还需要引用外界的数据,或是将自身的数据发送到外界,这时我们需要使用输入与输出. 1)输入与输出       输入:是一个从外界进入到程序的方向,通常我们需要"读取"外界的数据时,使用输入.所以输入是用来读取数据的 输出:是一个从程序发送到外界的方向,通常我们需要"写出"数据到外界时,使用输出.所以输出是用来写出数据的 2)节点流与处理流 按照流是否直接与特定的地方(如磁盘.内存.设备等)相连

java常见文件操作

收集整理的java常见文件操作,方便平时使用: //1.创建文件夹 //import java.io.*; File myFolderPath = new File(str1); try { if (!myFolderPath.exists()) { myFolderPath.mkdir(); } } catch (Exception e) { System.out.println("新建目录操作出错"); e.printStackTrace(); } //2.创建文件 //impor

Java字节码操作开源框架简介

avassist  Javassist是一个开源的分析.编辑和创建Java字节码的类库.是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的.它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架. BCEL  Byte Code Engineering Library (BCEL),这是Apache Software Foundation 的Jakarta 项目的一部分.BCEL是 Java classwor

第五篇 java字节码操作

java动态性的两种常见的实现方式: ①字节码操作 ②反射 运行时操作字节码可以让我们实现如下功能: ①动态生成新的类 ②动态改变某个类的结构(添加.删除.修改  新的属性或方法) 优点: 比反射的开销小,性能高 Javassist性能高于反射,低于ASM BCEL(Byte Code Engineering Library): 是java classworking 广泛使用的一种框架,它可以让你深入JVM汇编语言进行类操作的细节.BCEL与Javassist有不同的处理字节码的方法,BCEL在

java byte to hex

java  byte to hex 16 package com.longtop.client.codec.encryp; public class HexTransfer { /** * 将byte数组转换为表示16进制值的字符串, 如:byte[]{8,18}转换为:0813, 和public static byte[] * hexStr2ByteArr(String strIn) 互为可逆的转换过程 * * @param arrB * 需要转换的byte数组 * @return 转换后的字

JAVA使用和操作properties文件

java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properties文件中,可以用"#"来作注释,properties文件在Java编程中用到的地方很多,操作很方便.Properties 类存在于包 Java.util 中,该类继承自 Hashtable. 1. getProperty ( String  key) ,   用指定的键在此属性列表中搜索

WP8.1中C++的winodws运行时组件位移操作的差异

最近学习WP8.1应用开发,想把C语言的SM3国密算法移植到手机app中.由于把C语言的代码转换成C#代码工作量较大,因此只能用winodws运行时组件来实现. SM3国密算法是一种HASH算法,具体详情请自行百度. 结果测试发现手机上SM3算法计算出来的结果和电脑上运行的结果不同!经过我一点点调试发现是位移操作惹的祸,代码中有如下宏定义: #define SHL(x,n) (((x) & 0xFFFFFFFF) << n) #define ROTL(x,n) (SHL((x),n)