Java学习之==>int和Integer的区别和联系

一、区别

1、类型

  • int是java中原始八种基本数据类型之一;
  • Integer是一个类,包装整型提供了很多日常的操作;

2、存储位置和大小

  • int是由jvm底层提供,由Java虚拟机规范,int型数据存储在局部变量区,占用一个数据单元;
  • Integer型数据存储在Java运行时数据区的堆中,不在使用时可被垃圾回收机制回收;
    • Integer对象占用的存储空间大小:
      • Mark Word:4个字节,标记位;
      • Class对象指针:4字节,指向对应class对象的内存地址;
      • 对齐: 对齐填充字节,按照8个字节填充;
      • 4+4+8 = 16字节;

3、使用时字节码的区别

  • int型字节码示例:
    • 定义:int num1 = 32;
    • 字节码: 0: bipush 32;
  • Integer型字节码示例:
    • 定义:Integer num2 = 64;
    • 字节码:
      • 3:bipush 64;
      • 5:invokestatic #20 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

二、联系

1、相互转化

  • Integer.valueOf, int -> Integer;
  • Integer.intValue() Integer -> int;
  • 也可以直接相互赋值;

2、自动拆装箱操作(auto boxing/unboxing)

  • int -> Integer ,装箱;
  • Integer -> int, 拆箱;
  • 注意: 程序中尽量避免无意中的拆装箱操作,尤其是有性能考虑时;

3、自动装箱(int -> Integer)中缓存机制的分析

public static Integer valueOf(int i) {
  if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
    return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
  return new Integer(i);
valueOf
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 =
            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 Integer.IntegerCache.high >= 127;
  }

  private IntegerCache() {}
}
IntegerCache

  自动装箱操作会调用 Integer 的 valueOf() 方法,通过对以上源码分析发现:调用 valueOf() 方法时会先判断 int 型数据的数值范围,如果在Integer的缓存范围内,则调用IntegerCache类,如果不在 Integer 的缓存范围内,则直接 new 一个新的 Integer 对象。

  再看IntegerCache的源码,发现 Integer 缓存范围默认最小值是 -128,获取最大值时先会去读取 JVM 中配置的参数,如果配置了该参数值,则拿这个值和128比较取二者中更大的值作为 Integer 缓存的最大值,如果未配置该参数,则取128作为 Integer的最大值。

  下面我们来些个方法来证明以上分析,代码如下:

public void integerCache() {
  Integer i1 = 128;
  Integer i2 = 128;

  // false
  System.out.println(i1 == i2);

  Integer i3 = 127;
  Integer i4 = 127;

  // true
  System.out.println(i3 == i4);

  Integer i5 = 257;
  Integer i6 = 257;

  // false
  System.out.println(i5 == i6);
}

运行该方法结果如下:

127在缓存范围内,而128和257不再缓存范围内。

我们再加上JVM配置 -XX:AutoBoxCacheMax=256 后再次运行该方法结果如下:

证明配置生效,127和128在缓存范围内,257不再缓存范围内。以上结果证明我们对源码的分析是正确的。

注意事项:

  • 在做相等判断时,若为原始类型则可直接使用==,若为包装类型则需要使用equals;
  • 业务中若使用包装类型,要注意默认值是null,因为原始数据类型 int 的默认值是0容易让大家养成了习惯,这里最易疏忽;

4、扩展

猜你喜欢

转载自www.cnblogs.com/L-Test/p/11440827.html
今日推荐