近日在J2ME里做汉字编解码运算时,遇到一诡异问题,起初让我百思不得其解,并直叫见鬼了。
将问题简单描述如下:
汉字“国”的Unicode 编码值为22269,高字节为0x56 ,低字节为0xFD,于是我按照算法int ch=0x56<<8+0xfd 将ch理所当然地视为“国”的Unicode编码值ch==22269,但 char letter=(char)ch后,我发现letter=‘ી’是一乱码,而不是我所期待的“国”字。经验告诉我,debug的时候到了,通过debug发现,int ch=0x56<<8+0xfd计算得到的ch值是2752。
我百思不得其解,开始心烦意乱地胡乱猜疑,怀疑0x56<<8与0x56*256两个表达式的数值不相等,但大学里的知识告诉我将一个整数右移N位肯定等于该数乘以2的N次幂,Sytem.out.println((0x56<<8)==(0x56*256))运行的实际结果也否定了这次猜疑。于是我写了如下测试语句:
int highByte=0x56;
int lowByte=0xfd;
int chValue1=highByte<<8+lowByte;//2752
int chValue2=highByte*256+lowByte;//22269
char ch1=(char)chValue1;//乱码
char ch2=(char)chValue2;//'国'
通过debug发现,chValue1值为2752,转为char后是一个乱字符。chValue2值为22269,转为char后是我梦寐以求的“国”字,绝望地看着屏幕半小时后,我小心翼翼地分别给highByte<<8和highByte*256加了括号,发现得到的chValue1和chValue2都是我所期望的22269,于是我想到了运算符优先级的问题,猜测在java中<<的优先级低于+,在表达式highByte<<8+lowByte中,现计算8+lowByte,然后将得到的数值右移8位,实际程序的运行结果验证了我的想法, highByte<<8+lowByte和highByte<<(8+lowByte)结果相同都是2752。通过查找java运算符优先级顺序表(见下图),发现<<运算符确实低于+,是我没有注意正确的运算顺序导致了该问题的出现。
Java操作符的优先级和结合性
|
优先级
|
结合性
|
1
|
[ ].( ) (函数呼叫)
|
从左到右
|
2
|
!~++--+(单操作数)–(单操作数)( ) (类型转化)new
|
从右到左
|
3
|
*/%
|
从左到右
|
4
|
+-
|
从左到右
|
5
|
<<>>>>>
|
从左到右
|
6
|
<<=>>=instanceof
|
从左到右
|
7
|
==!=
|
从左到右
|
8
|
&
|
从左到右
|
9
|
^
|
从左到右
|
10
|
|
|
从左到右
|
11
|
&&
|
从左到右
|
12
|
||
|
从左到右
|
13
|
? :
|
从右到左
|
14
|
=+=-=*=/=%=^=<<=>>=>>>=
|
从右到左
|
结论:Java优先级顺序是很基本的常识,一个看起来让人悲伤欲绝的bug,查找出原因来很可能是因为一些很基本的常识没有注意到。在解决bug时,尽量保持平静的心态和,客观理性地查找原因。
分享到:
相关推荐
简单表达式由无结合的关系操作符组成(即无括号的表达式仅有一个关系操作符)。简单表达式在它不包含关系操作符时,其值是加法表达式的值,或者如果关系算式求值为t u r e,其值为1,求值为f a l s e时值为0。 22. ...
书中的步骤遵循由小到大、由浅入深的顺序,跟随这些步骤,读者可以由一个最简单的引导扇区开始,逐渐完善代码,扩充功能,最后形成一个小的操作系统。 本书不仅介绍操作系统的各要素,同时涉及开发操作系统需要的...
书中的步骤遵循由小到大、由浅入深的顺序,跟随这些步骤,读者可以由一个最简单的引导扇区开始,逐渐完善代码,扩充功能,最后形成一个小的操作系统。 本书不仅介绍操作系统的各要素,同时涉及开发操作系统需要的...
Source参数可以是一个Command对象名称、一段SQL命令、一个指定的数据表名称或是一个Stored Procedure。假如省略这个参数,系统则采用Recordset对象的Source属性。 ActiveConnection Recordset对象可以通过...
修复了一个问题,即在重命名相关的PCB文档后,Draftsman会崩溃。 26542 修复了回归,其中未选择丝网印刷图形的组件的装配视图中缺少阴影线(BC:9416)。 26867 修复了回归,其中没有显示缺少3D体的Not Fitted组件的...
select:从一个或多个表中检索一个或多个数据列。包含信息:想选择什么表,从什么地方选择。必须要有From子句。(最常用) 当从多张表里查询的时候,会产生笛卡尔积;可用条件过滤它。 当两个表有相同字段时必须加...
15.用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数 A1: 16位的系统下, int i = 65536; cout ; // 输出0; int i = 65535; cout ; // 输出-1; 32位的系统下, int i = 65536; cout ; ...
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...
0301 系统接收了一个无效的操作锁定确认。 0317 在 %2 的消息文件中,系统无法找到消息号为 0x%1 的消息文本。 0487 试图访问无效地址。 0534 运算结果超过 32 位。 0535 该管道的另一方有一进程。...
(如果你安装的 IE 是 5.x 或更高版本, 那么就不必担心这个问题了) 注意: Windows 3.1(和 NT3.5x), 请使用 IP Messenger for Win16. 使用说明 安装/卸载 > 执行 setup.exe 你可以将 IPMsg 安装到指定目录, ...
10.2.4 指针变量几个问题的进一步说明 140 810.3 数组指针和指向数组的指针变量 141 10.3.1 指向数组元素的指针 142 10.3.2 通过指针引用数组元素 143 10.3.3 数组名作函数参数 146 10.3.4 指向多维数组的指针和指针...
10.2.4 指针变量几个问题的进一步说明 140 810.3 数组指针和指向数组的指针变量 141 10.3.1 指向数组元素的指针 142 10.3.2 通过指针引用数组元素 143 10.3.3 数组名作函数参数 146 10.3.4 指向多维数组的指针和指针...
让默认的就可以了,但是超频玩者是肯定不会放过任何可以提高性能的东西的,所以如果你想在这里让你的电脑提升一点性能的话,就必须慢慢试验,选择一个适当的参数才能让你的计算机达到性能和稳定的最佳状态!...
(如果你安装的 IE 是 5.x 或更高版本, 那么就不必担心这个问题了) 注意: Windows 3.1(和 NT3.5x), 请使用 IP Messenger for Win16. ---------------------------------------------------------------------...
8. 修改引导菜单显示:当只有一个NT5.x和n个NT6.x系统时,如对"早期版本windows"或"Earlier Version of Windows"菜单感到不爽,直接"自动修复/手动修复"将自动修改相应菜单为实际系统类型模式 9. 实例 - Ghost系统...
1.3 第一个程序—Hello World 8 1.4 小结 11 1.5 习题 12 第二篇 面向对象基础篇 第2章 类和对象 16 2.1 分析Hello World程序 16 2.2 语法规范 17 2.2.1 标识符 17 2.2.2 关键字 18 2.2.3 注释 19 2.3 定义类 20 ...
(如果你安装的 IE 是 5.x 或更高版本, 那么就不必担心这个问题了) 注意: Windows 3.1(和 NT3.5x), 请使用 IP Messenger for Win16. ---------------------------------------------------------------------...
//用下面命令可以得到一个硬盘的微码级别: # lscfg -vl pdisk* //IBM小型机AIX5.1操作系统密码文件丢失或者误删的恢复方法 进入维护模式: 1、将安装盘第一张放入光驱; 重启小型机选择主控台,按屏幕上提示的数字;...