int i = 1,Integer j = new Integer(1)即Integer j= 1;问 i==j 吗?为什么?
java中,每个基本数据类型都是与类(包装类)相对应的:
int对应的类是Integer;char对应的类是Character;float对应的类是Float;long对应的类是Long
byte对应的类是Byte;short对应的类是Short;double对应的类是Double;boolean对应的类是Boolean
一、
1)int则是java的一种基本数据类型,其定义的是基本数据类型变量 ;Integer是int的包装类,其定义的是引用类型变量
2)基本数据类类型存的是数值本身;引用类型变量在内存放的是数据的引用
3) 基本类型比较的是他们的值大小(通过==),而引用类型比较的是他们的引用地址
4) Integer变量必须实例化后才能使用,而int变量不需要
5)Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
6)Integer的默认值是null,int的默认值是0
二、
Integer和int的比较
1)由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.print(i == j); //false
2)Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动将Integer拆箱为int,然后进行比较,实际上就变为两个int变量的比较)
Integer i = new Integer(1);
int j = 1;
System.out.print(i == j); //true
3)非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer i = new Integer(1);
Integer j = 1;
System.out.print(i == j); //false
4)对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 110;
Integer j = 110;
System.out.print(i == j); //true(因为-128到127java已经进行了缓存,所以i和j指向的是同一块内存,即同样的引用地址)
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
java在编译Integer i = 110 时,会翻译成为Integer i = Integer.valueOf(110);而java API中对Integer类型的valueOf的定义如下:
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了
三、
举例:
注意:
①Integer与new Integer不会相等。不会经历拆箱过程,
②两个都是非new出来的Integer,如果数在-128到127之间则是true,否则为false ;java在编译Integer i2 = 128的时候,
被翻译成 Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
③两个都是new出来的,引用地址不同,false
④int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比
解析:
A: Integer 与 int 比较的时候将Integer拆箱转成int,然后再比较大小,true
B: Integer i01 = 59;默认处理Integer i01 =Integer.valueOf(59); i01与 i03数值在-128 - 127之间,所以在cache缓存中获取Integer对象,他们引用地址是一样的。true
C: i03获取的是cache中缓存好的的Integer地址,而i04是重新在堆中创建一个地址,所以两个地址是不一样的 .false
D:同A
其实Integer与int类型的赋值与比较最关键的一点就是:这两个变量的类型不同。Integer是引用类型,int是原生数据类型。
我们分四种情况来讨论:
1) Integer与int类型的赋值
a.把Integer类型赋值给int类型。此时,int类型变量的值会自动装箱成Integer类型,然后赋给Integer类型的引用,这里底层就是通过调用valueOf()这个方法来实现所谓的装箱的。
b.把int类型赋值给Integer类型。此时,Integer类型变量的值会自动拆箱成int类型,然后赋给int类型的变量,这里底层则是通过调用intValue()方法来实现所谓的拆箱的。
2) Integer与int类型的比较
这里就无所谓是谁与谁比较了,Integer == int与int == Integer的效果是一样的,都会把Integer类型变量拆箱成int类型,然后进行比较,相等则返回true,否则返回false。同样,拆箱调用的还是intValue()方法。
3) Integer之间的比较
这个就相对简单了,直接把两个引用的值(即是存储目标数据的那个地址)进行比较就行了,不用再拆箱、装箱什么的。
4) int之间的比较
这个也一样,直接把两个变量的值进行比较。
值得注意的是:对Integer对象,JVM会自动缓存-128~127范围内的值,所以所有在这个范围内的值相等的Integer对象都会共用一块内存,而不会开辟多个;超出这个范围内的值对应的Integer对象有多少个就开辟多少个内存。
四、
堆和栈的区别是什么?
堆和栈是编译器划分的内存空间。
栈上分配的内存,编译器会自动收回;堆上分配的内存,要通过free来显式地收回。
栈是系统自动分配,堆是需要程序员自己申请(new出来)
哪些变量会在栈中分配空间,哪些变量会在堆中分配空间?
函数局部变量、参数,一些临时对象都在栈中分配空间。全局变量存储在堆中分配空间。