int与Integer区别

int与Integer的区别
  • Integer是int的包装类;int是基本数据类型;
  • Integer变量必须实例化后才能使用;int变量不需要;
  • Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
  • Integer的默认值是null;int的默认值是0。
  • 泛型不支持int,但是支持Integer
  • int 存储在栈中,Integer 对象的引用存储在栈空间中,对象的数据存储在堆空间中。
分析

int

int 是java的基本数据类型。

Integer

Integer 继承了Object类,是对象类型,是 int 的包装类。
Java两种数据类型
  • 基本数据类型,分为boolean、byte、int、char、long、short、double、float;
  • 引用数据类型 ,分为数组、类、接口、枚举、标注。
Java原始类型的封装类

为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每 一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

基本类型

包装类型

byte

Byte

short

Short

int

Integer

long

Long

float

Float

double

Double

char

Character

boolean

Boolean

自动装箱和自动拆箱

自动装箱:将基本数据类型重新转化为对象

public class Demo {  
        public static void main(String[] args) {  
            //声明一个Integer对象
            Integer num = 1;
            //以上的声明就是用到了自动的装箱:解析为:Integer num = new Integer(1);
        }  
}

1是属于基本数据类型的,原则上它是不能直接赋值给一个对象Integer的。但jdk1.5后你就可以进行这样的声明,自动将基本数据类型转化为对应的封装类型,成为一个对象以后就可以调用对象所声明的所有的方法。

自动拆箱:将对象重新转化为基本数据类型

public class Demo {
    public static void main(String[] args) {
        //自动装箱 将基本数据类型变成对象
        Integer integer = 1;
        //自动拆箱
        System.out.println(integer+10);
    }
}

因为对象是不能直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除。

对比:

// 装箱
Integer a = 10;
// 拆箱
int b = a;
相同值下的 int 和 Integer 的比较结果
  1. 两个通过new生成的变量,结果为false。
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.print(i1 == i2); //false
  1. int 和 Integer 的值比较,若两者的值相等,则为true。(注意:在比较时,Integer会自动拆箱为int类型,然后再做比较,实际上就变为两个int变量的比较)
Integer i1 = new Integer(10);
int i2 = 10;
System.out.print(i1 == i2); //true
  1. new 生成的Integer变量 和 非new 生成的Integer变量比较,结果为false。(注意:new 生成的Integer变量的值在堆空间中,非new 生成的Integer变量的值在在常量池中。非new生成的Integer变量,会先判断常量池中是否有该对象,若有则共享,若无则在常量池中放入该对象;这也叫享元模式)
Integer i1 = new Integer(10);
Integer i2 = 10;
System.out.print(i1 == i2); //false
  1. 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。
Integer i1 = 10;
Integer i2 = 10;
System.out.print(i1 == i2); //true
Integer j1 = 128;
Integer j2 = 128;
System.out.print(j1 == j2); //false

当值在 -128 ~ 127之间时,java会进行自动装箱,然后会对值进行缓存,如果下次再有相同的值,会直接在缓存中取出使用。缓存是通过Integer的内部类IntegerCache来完成的。当值超出此范围,会在堆中new出一个对象来存储。

源码分析

我们先看下Integer的构造函数源码

/**
     * Constructs a newly allocated {@code Integer} object that
     * represents the specified {@code int} value.
     *
     * @param   value   the value to be represented by the
     *                  {@code Integer} object.
     */
    public Integer(int value) {
        this.value = value;
    }
/**
 * Constructs a newly allocated {@code Integer} object that
 * represents the {@code int} value indicated by the
 * {@code String} parameter. The string is converted to an
 * {@code int} value in exactly the manner used by the
 * {@code parseInt} method for radix 10.
 *
 * @param      s   the {@code String} to be converted to an
 *                 {@code Integer}.
 * @exception  NumberFormatException  if the {@code String} does not
 *               contain a parsable integer.
 * @see        java.lang.Integer#parseInt(java.lang.String, int)
 */
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

Integer提供了两种构造方法,一种是初始化数字,一种是使用String通过内部的parseInt将字符转换成数字

JDK1.5之后,java提供了自动装箱和自动拆箱的功能。自动装箱也就是调用了Integer类的一个静态方法valueOf方法,源码如下:

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

源码中有一个IntegerCache,这是一个私有的内部类。这个类缓存了low - high之间数字的包装类。我们可以看到源码中的解析为:

  • 缓存支持自动装箱的对象标识语义 -128和127(含),
  • 缓存在第一次使用时初始化。 缓存的大小可以由-XX:AutoBoxCacheMax = 选项控制。
  • 在VM初始化期间,java.lang.Integer.IntegerCache.high属性可以设置并保存在私有系统属性中

如果判断成立就把缓存中的那个包装类返回,反之则new一个新的。这样我们也就明白了上面第四点Integer比较结果为false的原因了。

/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */

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 IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}