Integer和int的关系

1,113 阅读4分钟

类型

Java的两种类型

  1. 基本类型,存放的是数据的本身
  2. 引用类型,存放的是被引用对象的地址

比较方式

  1. 基本类型之间的比较是通过比较值
  2. 引用类型之间的比较是比较地址

例子

public class Test03 {
 
    public static void main(String[] args) {
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        System. out.println( f1 == f2); //true
        System. out.println( f3 == f4); //false
    }
}

解释:

Integer在Java中是一个类,所以上诉的f1 - f4都是引用变量,而引用变量存储的应该是地址,也就是一个对象的地址,而不是这些十进制的常量,难道这样就出错了吗?其实并没有,只是编译器帮我们做了一些事情而已。

当我们给Integer的引用赋给一个int的变量的时候,编译器会自动调用这个Integer.valueOf(int a)静态方法,也就是说

Integer f1 = 100 实际上就是 Integer f1 = Integer.valueOf(100); 也就是会返回一个对象的地址给f1这个引用。

问题来了,在我们的印象中,在Java创建两个不同的对象,返回的肯定不是同一个地址。那么上面说引用类型比较的是比较地址的值,f1 == f2 就会返回ture呢?(思考三秒钟....)既然返回true,那肯定是说值相等嘛,又因为地址又是唯一的,所以只能是返回给f1和f2的地址是同一个!下面的源码可以验证这个说法

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)//这里的low是-128,high是127
            return IntegerCache.cache[i + (-IntegerCache.low)]; // 这里说只要在-128~127这个返回,就会返回已经创建好的对象,这些对象就是存放在一个cache数组里面的。所以只要i是一样的,那么返回的对象也就是同一个。
        return new Integer(i);// 如果执行这一步,那么说明只能创建一个新的对象了,创建新对象,那么就表示所返回的地址肯定不一样啦!
}

下面我们来看下Integer的cache数组就知道了

cache = new Integer[(high - low) + 1]; //定于数组的大小
int j = low;
for( int k = 0; k < cache.length ; k ++) //每个数组存储了一个Integer对象,对象的values的范围就是-128~127
    cache[k] = new Integer(j ++);

所以在例子1中,f3和f4由于在执行Integer.ValueOf(int value )的时候,由于传给value(150)的值已经大于127,所以,就直接返回一个新的对象。,所以在f3 == f4的时候,引用对象比较的是地址的值,地址肯定是不一样的,所以就是false啦!

区别

在上诉的例子中,我们说的是Integer = value( -128<=value<=127)的时候,就会返回这些已经创建好的Integer对象。

但是并不代表着值是 这个范围(-128~127)的Integer对象就是同一个对象,先看下面代码!

    Integer a = new Integer(3); 
    Integer b = 3;                 
    int c = 3;
    System.out.println(a == b);    
    System.out.println(a == c); 

Integer a = new Integer(3);

这条语句会直接在Java的堆中创建一个Integer的实例对象,值是3,也就是说之前Java内存中没有的这个对象现在被创建出来了。

Integer b = 3;

这条语句就是像之前所说的,会调用静态方法Integer.valueOf(value),返回的是一个内存(也就是Integer.cache数组)中已经存在的Integer对象。

由上面的分析可知,a的值,也就是a表示的地址肯定和b不一样,因为都是不同的对象。所以a == b 会返回false

a == c

如果一个是Integer和int 比较,那么则会把Integer 转化为int,然后由于两个都是基本类型,所以比较的是值是否相等,所以这里肯定返回的是true

扩展

Java中还有与Integer类似的是Long,它也有一个缓存,在区间[-128,127]范围内获取缓存的值,而Long与long比较的时候先转换成long类型再做值的比较

Double类型,它没有缓存,但是当Double与double比较的时候会先转换成double类型,再做值的比较