==
和 equals
- 当基本数据类型的包装类使用
=
时,会使用XXX.valueOf()
,会走 cache- 如果在 cache 外,那么进行
==
时,即使值一样,引用也绝对不一样 - 这也是为什么基本数据类型只能用
==
比较值,而引用数据类型只能用equals
比较值
- 如果在 cache 外,那么进行
测试
public static void main(String[] args) {
/*
== 比较地址
*/
Integer a = 2;
Integer b = 2;
Integer c = new Integer(2);
System.out.println(a == b); // true
System.out.println(a == c); // false
Integer aa = 150; // 使用 Integer.valueOf(150)
Integer bb = 150;
Integer cc = new Integer(150);
System.out.println(aa == bb); // false
System.out.println(aa == cc); // false
Integer aaa = 150;
System.out.println(aaa == 150); // true, 装箱拆箱,比较值而不是地址
}
Integer和Long
IntegerCache
- 直接赋值和
Integer.valueOf()
会使用到缓存 看源码
String integerCacheHighPropValue=sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”)
;
可以带上参数
-XX:AutoBoxCacheMax=xxx
来 设置缓存数值上限,即 [-128~xxx]// IntegerCache
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
// 可以通过 -XX:AutoBoxCacheMax=xxx 设置
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
建议使用
valueOf
而不是parseInteger
LongCache
直接赋值和
Long.valueOf()
会使用到缓存// LongCache
private static class LongCache {
private LongCache(){}
// -128~127 的长度, +1 是因为有0
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
// 缓存 -128~127
cache[i] = new Long(i - 128);
}
}
建议使用
valueOf
而不是parseLong
BigDecimal
初始化
- 使用
BigDecimal
表示和计算浮点数,且务必使用字符串的构造方法来初始化BigDecimal
- 如果一定要用
Double
来初始化BigDecimal
的话,可以使用BigDecimal#valueOf()
- scale 表示小数点右边的位数,而 precision 表示精度,也就是有效数字的长度。
- scale 可能会变化,比如
BigDecimal#multiply
,会让 scale 相加
格式化
- 浮点数的字符串格式化也要通过 BigDecimal 进行 ```java BigDecimal num1 = new BigDecimal(“3.35”); // 指定格式方式 BigDecimal num2 = num1.setScale(1, BigDecimal.ROUND_DOWN); System.out.println(num2);
BigDecimal num3 = num1.setScale(1, BigDecimal.ROUND_HALF_UP); System.out.println(num3); ```
比较
BigDecimal#equals()
比较的是BigDecimal
的value
和scale
- 如果要用于比较,可以用
BigDecimal#compareTo()
- 如果要用于比较,可以用
BigDecimal
存储进 HashMap 有问题,因为后者是比较equals
- 使用 TreeMap 代替,后者使用
compareTo
进行比较 - 将元素使用
BigDecimal#stripTrailingZeros()
将尾部的0去除,就可以存储到 HashMap 中了
- 使用 TreeMap 代替,后者使用
溢出
- 使用
Math
类的addExact
、subtractExact
等 xxExact 方法进行数值运算,这些方法可以在数值溢出时主动抛出异常ArithmeticException
- 使用
BigInteger
,比如在将计算结果转换一个Long
变量的话,可以使用BigIntegr#longValueExact()
方法,在转换出现溢出时,同样会抛出 ArithmeticException