趁有空,赶紧刷刷论坛凑凑技术分。这个是本人最近看过的一些有意思的Java小问题,贴出来给大家分享下。
public static boolean isOdd(int i) { return i%2==1; } 这个方法的目的是确定其唯一的参数i是否为奇数。 奇数定义为被2整除余数为1的整数。 看起来此方法可行,但遗憾的是在1/4时间内它返回的都是错误答案。 原因:所有int数值中,一半是负数。isOdd对负奇数判断都会失败。任何负整数都会返回false。 改正: public static boolean isOdd(int i){ return(i&1)!=0; } 第二个: public class LongDivision{ public static void main(String [] args){ final long MICROS_PER_DAY=24*60*1000*1000; final long MILLIS_PER_DAY=24*60*1000; System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); } } 此程序想打印什么呢?很显然一天的毫秒数和一天的微秒数都是常量,一约分得到的结果是1000,也就是一毫秒里包含1000微秒。被除数和除数都是long,结果肯定不会溢出。 但是它打印出来是5。 原因:在于MICROS_PER_DAY的计算确实溢出了。这个运算是在int中完成的,计算完之后其结果才转换成long。MICROS_PER_DAY保留了不正确的数值但MILLIS_PER_DAY数值正确,所以整除结果是5。为什么是int类型的运算呢?因为所有乘在一起的因子都是int数值。Java不具有目标确定类型(存储结果的类型会影响计算所使用的类型)的特性。 改正: public class LongDivision{ public static void main(String [] args){ final long MICROS_PER_DAY=24L*60*1000*1000; final long MILLIS_PER_DAY=24L*60*1000; System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); } } 即使保存结果的变量足够大,也并不意味着计算过程有正确的类型。提放溢出。 第三个:两个16进制常量相加,打印16进制结果。最后输出是什么呢? public class JoyOfHex{ public static void main(String[] args){ System.out println( Long.toHexString(0x100000000L+0xcafebabe)); } } 该程序想打印1cafebabe。16进制100000000与16进制cafebabe相加,long型运算支持16进制。所以不可能溢出。但是打印出来的是cafebabe。没有“1”。 原因:0xcafebabe是int常量,其最高位被置位了,是一个负数:-889275714。 该程序是一个混合加法计算。左边操作数是long而右边是int。计算时Java将int转换成long,因为int是有符号整数类型,所以转换执行的是符号扩展:将负的int类型转换成数值相等的long类型。转换后变成了0xffffffffcafebabeL+0x0000000100000000L,两个最高位-1+1=0,所以结果为0x00000000cafebabeL。 改正: public class JoyOfHex{ public static void main(String[] args){ System.out println( Long.toHexString(0x100000000L+0xcafebabeL)); } } 最好避免混合类型计算
|