1. 打包和拆包
Integer a = 1000;
Integer b = 1000;
if (a == b) ...
a == b, 有可能成立。如果将经常出现的值包装到同一个对象中,这种比较就有可能成立。解决这个问题的办法是在比较两个包装器对象时调用equals方法。
自动打包规范中要求当 boolean、char( 小于等于 127)、(byte、short、int: (介于 -128 ~
127 之间))时,它们被包装到固定对象中。例如,如果在上面的代码中,如果a和b初始化为100,那么,对它们进行的比较则一定成立。
// 以下三个方法可以解释Tip1的行为。
// 第三个方法是为了说明显示的实例化两个Integer对象,它们肯定不会是同一的。
// java.lang.Integer 类中的静态内部类
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
// 打包
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
// 创建实例
public Integer(int value) {
this.value = value;
}
注意,打包和拆包是编译器认可的,而不是虚拟机。
2. 整型溢出(基本数据类型的变窄转换)
int i = 1000000;
System.out.println(i*i);
// result: -727379968
合理解释和过程应该是这样的:
i设置为1000000,在乘方时Java发现结果(1000000000000)已经超出了int基本数据类型的最大范围(2147483647),于
是作了默认的类型提升(type
promotion),中间结果做为long类型存放,返回结果时目标数据类型int不能够容纳下结果,于是根据Java的基础类型的变窄转换
(Narrowing primitive
conversion)规则,把结果宽于int类型宽度的部分全部丢弃,也就是只取结果的低32位,于是就得到了上面的结果。
下面用一个十六进制表示的例子阐释这个问题
int i3 = 1000000;
System.out.println (Long.toHexString(i3*i3).toUpperCase());
System.out.println (Long.toHexString(i3*i3).toUpperCase());
System.out.println (Integer.toHexString(i3*i3).toUpperCase());
System.out.println ((int)i3*i3);
// result:
// FFFFFFFFD4A51000
// 1000000000000
// D4A51000
// -727379968
截取是非常直观的 .
3. 精度
JAVA中浮点数值不适用于禁止出现舍入误差的金融计算中。例如,System.out.println(2.0 - 1.0) 将打印出0.899999999999999,而不是0.9。其主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确的表示分数1/10,就像十进制无法精确的表示1/3一样。如果需要在数值计算中不含有任何舍入误差,就应该使用BigDecimal类。
4. char
分享到:
2010-03-08 16:45
浏览 554
评论