==equals

  • 当基本数据类型的包装类使用 = 时,会使用 XXX.valueOf() ,会走 cache
    • 如果在 cache 外,那么进行 == 时,即使值一样,引用也绝对不一样
    • 这也是为什么基本数据类型只能用==比较值,而引用数据类型只能用equals比较值
  • 测试

    1. public static void main(String[] args) {
    2. /*
    3. == 比较地址
    4. */
    5. Integer a = 2;
    6. Integer b = 2;
    7. Integer c = new Integer(2);
    8. System.out.println(a == b); // true
    9. System.out.println(a == c); // false
    10. Integer aa = 150; // 使用 Integer.valueOf(150)
    11. Integer bb = 150;
    12. Integer cc = new Integer(150);
    13. System.out.println(aa == bb); // false
    14. System.out.println(aa == cc); // false
    15. Integer aaa = 150;
    16. System.out.println(aaa == 150); // true, 装箱拆箱,比较值而不是地址
    17. }

Integer和Long

IntegerCache

  • 直接赋值和 Integer.valueOf() 会使用到缓存
  • 看源码

    String integerCacheHighPropValue=sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”);

    • 可以带上参数 -XX:AutoBoxCacheMax=xxx设置缓存数值上限,即 [-128~xxx]

      1. // IntegerCache
      2. private static class IntegerCache {
      3. static final int low = -128;
      4. static final int high;
      5. static final Integer cache[];
      6. static {
      7. // high value may be configured by property
      8. int h = 127;
      9. String integerCacheHighPropValue =
      10. // 可以通过 -XX:AutoBoxCacheMax=xxx 设置
      11. sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
      12. if (integerCacheHighPropValue != null) {
      13. try {
      14. int i = parseInt(integerCacheHighPropValue);
      15. i = Math.max(i, 127);
      16. // Maximum array size is Integer.MAX_VALUE
      17. h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
      18. } catch( NumberFormatException nfe) {
      19. // If the property cannot be parsed into an int, ignore it.
      20. }
      21. }
      22. high = h;
      23. cache = new Integer[(high - low) + 1];
      24. int j = low;
      25. for(int k = 0; k < cache.length; k++)
      26. cache[k] = new Integer(j++);
      27. // range [-128, 127] must be interned (JLS7 5.1.7)
      28. assert IntegerCache.high >= 127;
      29. }
      30. private IntegerCache() {}
      31. }

      建议使用 valueOf 而不是 parseInteger

LongCache

  • 直接赋值和 Long.valueOf() 会使用到缓存

    1. // LongCache
    2. private static class LongCache {
    3. private LongCache(){}
    4. // -128~127 的长度, +1 是因为有0
    5. static final Long cache[] = new Long[-(-128) + 127 + 1];
    6. static {
    7. for(int i = 0; i < cache.length; i++)
    8. // 缓存 -128~127
    9. cache[i] = new Long(i - 128);
    10. }
    11. }

    建议使用 valueOf 而不是 parseLong


BigDecimal

初始化

  1. 使用 BigDecimal 表示和计算浮点数,且务必使用字符串的构造方法来初始化 BigDecimal
  2. 如果一定要用 Double 来初始化 BigDecimal 的话,可以使用 BigDecimal#valueOf()
    1. scale 表示小数点右边的位数,而 precision 表示精度,也就是有效数字的长度。
    2. scale 可能会变化,比如 BigDecimal#multiply ,会让 scale 相加

格式化

  1. 浮点数的字符串格式化也要通过 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); ```

比较

  1. BigDecimal#equals() 比较的是 BigDecimalvaluescale
    1. 如果要用于比较,可以用 BigDecimal#compareTo()
  2. BigDecimal 存储进 HashMap 有问题,因为后者是比较 equals
    1. 使用 TreeMap 代替,后者使用 compareTo 进行比较
    2. 将元素使用 BigDecimal#stripTrailingZeros() 将尾部的0去除,就可以存储到 HashMap 中了

溢出

  1. 使用 Math 类的 addExactsubtractExact 等 xxExact 方法进行数值运算,这些方法可以在数值溢出时主动抛出异常 ArithmeticException
  2. 使用 BigInteger ,比如在将计算结果转换一个 Long 变量的话,可以使用 BigIntegr#longValueExact() 方法,在转换出现溢出时,同样会抛出 ArithmeticException