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();
}
分享到:
相关推荐
### 注意事项 - 在处理字节序问题时,需要注意Java默认使用的是大端字节序。如果你需要与使用小端字节序的系统通信,你需要在转换过程中调整字节的顺序。 - 当转换大型整数(如long)时,上述方法不再适用,因为...
7. **注意事项**: - 位移操作可能涉及到溢出问题,需要确保操作在安全范围内。 - 在处理负数时,特别是在位移和字节转换中,需要特别小心,因为负数的二进制表示(补码)可能会导致预期外的结果。 在"Cnic....
**注意事项**: - 当对byte或short类型进行移位操作时,它们会被提升为int类型,因此移位结果可能超出原始类型的范围,需要额外处理。 - 左移可能会导致符号位丢失,尤其是对负数左移过多位时。 - 右移时,如果原始...
- **注意事项**: 非公共类(即默认访问级别或包私有级别)可以在同一个`.java`文件中定义多个,它们不会与文件名冲突。 **2. Java有没有goto?** - **知识点**: Java语言标准中并未定义`goto`关键字,但在`switch`...
MD5(Message-Digest Algorithm 5)是一种...通过阅读`md5.docx`文档,你可以找到更具体的Java MD5加密实现细节,以及可能包含的使用示例和注意事项。在实际开发中,理解并正确使用MD5加密技术对于数据安全至关重要。
根据给定文件的信息,我们可以总结出以下几个重要的Java知识点: ...通过以上知识点的介绍,我们不仅了解了Java的基本语法,还学习了一些常见的陷阱和注意事项,这对于深入理解和掌握Java语言非常有帮助。
下面我们将详细探讨MD5加密的基本原理、Java实现MD5加密的过程以及相关的注意事项。 MD5的工作原理是接收任意长度的数据,通过一系列的数学运算(如位移、异或、加法等)将其转化为固定长度的128位二进制数,也就是...
- **注意事项**: 构造器不能返回任何值,但可以有 `return` 语句,此时 `return` 后不能有任何其他语句。 **5. super() 和 this() 的使用** - **知识点**: `super()` 和 `this()` 必须在构造函数的第一行使用。 ...
4. **特殊注意事项**: - `!`逻辑非运算符不能与`=`, `+=`, `-=`, `*=`, `/=`, `%=`等赋值运算符联用,因为它是一元运算符。 - 在进行位运算时,不能对布尔类型的变量进行按位非操作。 - 移位运算符在处理`Char`,...
- **注意事项**:如果没有显式定义构造方法,系统会自动添加一个默认构造方法。 #### 19. 成员变量赋值 - **方式**: - 直接在声明时赋初值。 - 通过构造方法初始化。 - 在类的方法中赋值。 #### 20. 方法重写...
而`README.txt`可能是对程序的解释,包括如何运行程序、输入和输出的格式以及可能的注意事项。 为了增强安全性,通常不建议使用默认的ECB模式,因为它存在重复模式的问题。更推荐使用CBC(Cipher Block Chaining)...
**注意事项:** - 使用`synchronized`关键字可以解决某些特定情况下的线程安全问题,但可能会导致性能瓶颈。 - 对于复杂的多线程场景,应考虑使用更高级的同步机制,如`ReentrantLock`等。 #### 三、EJB Session ...
### 六、注意事项 1. **密钥和初始化向量**:AES加密需要一个128位的密钥和一个128位的初始化向量。确保密钥的安全存储。 2. **错误处理**:在实际应用中,需要对OpenSSL的返回值进行检查,处理可能出现的错误。 ...
4. **安全注意事项**:除了加密,还应考虑其他安全措施,如使用盐值(salt)增加密码的复杂性,使用哈希函数进一步增强安全性,以及定期更换密钥。 在标签中提到的"源码"和"工具"可能意味着该压缩包包含了一个名为...
5. **安全注意事项**:尽管MD5在很多场景下仍被使用,但因其已知的碰撞漏洞,不适合用于高度安全的应用,比如现代密码存储。现在更推荐使用SHA-256或更强的哈希算法,并配合加盐(Salt)和多次迭代以增加安全性。 6...
- 位移操作符(、>>)的使用方法。 - **7.7 其它特殊操作符** - 如条件操作符(?:)、大小操作符(as)等。 - 特殊操作符的使用场合。 - **7.8 小结** - 本章详细介绍了C#中的各种操作符和表达式,包括算术、...