1. 装包和拆包

java提供的基本类型以及其对于的包装类型

基本类型 对于包装类型
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double
void Void

下面以Integer为例子介绍装箱和拆箱:

装箱存在的情况:

int 赋值给Integer 即基本类型赋值给包装类型时
等价于 Integer i = Integer.valueOf(1); java自动完成装箱操作

  1. Integer i = 1;


拆箱存在的情况:

int与Integer比较 及基本类型和包装类型比较时
i对象会自动拆箱int类型和j进行比较

  1. new Integer(1) == 1// 等价于 i.intValue() == j

2. Integer原理及缓存机制

Integer是int基本数据类型的包装类,无非是在int基本类型的基础上增加了一些操作和其他属性。
Integer的实际对应int值是通过intValue()方法获取的,源码如下:

  1. public final class Integer extends Number implements Comparable<Integer> {
  2. @Native public static final int MIN_VALUE = 0x80000000;
  3. @Native public static final int MAX_VALUE = 0x7fffffff;
  4. // 对应int基本类型的数值 是一个常量整型
  5. private final int value;
  6. public int intValue() {
  7. return value;
  8. }
  9. ...省略
  10. }

前面说过的装箱用到的一个方法是valueOf(),让我们看看源码:
可以看到传入的i 先和IntegerCache比较 在IntegerCache中则返回IntegerCache中的Integer不存在则new一个Integer对象

  1. public static Integer valueOf(int i) {
  2. if (i >= IntegerCache.low && i <= IntegerCache.high)
  3. return IntegerCache.cache[i + (-IntegerCache.low)];
  4. return new Integer(i);
  5. }

IntegerCache实现如下:
IntegerCache是个Integer的内部类,在类加载的时候static代码块创建了256个缓存Integer对象,范围-128至127

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

知道Integer缓存的存在,下面我们看看下面的几个例子:
注:== 对象比较比较的是对象的引用是否相等 equals则根据对象内部的实现情况进行比较

  1. Integer i = 1; //i = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
  2. Integer j = 1; //j = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
  3. System.out.println(i == j);//输出true i 和j指向同一个对象
  1. Integer i = 1; //i = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
  2. Integer j = new Integer(1); // 新创建一个对象
  3. System.out.println(i == j);//输出false i 和j指向的不是同一个对象
  1. Integer i = 128; //i = Integer.valueOf(128) 不在缓存访问内 new Integer(128)
  2. Integer j = 128; //j = Integer.valueOf(128) 不在缓存访问内 new Integer(128)
  3. System.out.println(i == j); //输出false i 和j指向的不是同一个对象

所以Integer对象在比较是否相等的时候 不要用 == 用equals Integer内部实现了自己用equals,源码如下:

  1. public boolean equals(Object obj) {
  2. if (obj instanceof Integer) {
  3. return value == ((Integer)obj).intValue();
  4. }
  5. return false;
  6. }