一、
int和Integer的区别:
1. Integer是int的包装类,Integer也是一个类,int则是java的一种基本数据类型
2. Integer变量必须实例化后才能使用,而int变量不需要
3. Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4. 在类进行初始化时,Integer的默认值是null,int的默认值是0
延伸:
关于Integer和int的比较
1. 由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
2. Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true
3. 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false
4. 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
对于第4条的原因:
java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而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了。
二、以下代码实例来充分说明
public class integerTest {
public static void main(String[] args) {
int i = 128;
Integer i2 = 128;
Integer i3 = new Integer(128);
// Integer会自动拆箱为int,所以为true
//11行和12行输出结果都为true,因为Integer和int比都会自动拆箱(jdk1.5以上)
System.out.println(i == i2); //true
System.out.println(i == i3); //true
System.out.println("**************");
// java在编译的时候,被翻译成-> Integer i5 = Integer.valueOf(127);
// 看一下源码大家都会明白,对于-128到127之间的数,会进行缓存,Integer i5 = 127时,
//会将127进行缓存,下次再写Integer i6 = 127时,就会直接从缓存中取,就不会new了。
Integer i5 = 127;
Integer i6 = 127;
System.out.println(i5 == i6);// true
Integer _i5 = 128;
Integer _i6 = 128;
System.out.println(_i5 == _i6);//false
Integer ii5 = new Integer(127);
System.out.println(i5 == ii5); // false
Integer i7 = new Integer(128);
Integer i8 = new Integer(128);
System.out.println(i7 == i8); // false
}
}
对上代码分析:
(1)无论如何,Integer与new Integer不会相等。不会经历拆箱过程。ii5的引用指向堆,而i5指向常量池中的对象,他们的内存地址不一样,所以为false。
(2)两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false。java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存。
(3)两个都是new出来的,都为false。
(4)int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比。
(5)int是在栈里创建的,Integer是在堆里创建的。栈里创建的变量要比在堆创建的速度快得多。
Java里面“==”与equals()的区别:前者比较的是地址,后者比较的是内容。
三、再次解读int基本数据类型与Integer包装类型的微妙关系
1. 初始化时,int i =1;
Integer i= new Integer(1);(要把Integer 当做一个类看);但由于有了自动装箱和拆箱(始于jdk1.5),使得对Integer类也可使用:Integer i= 1;
int是基本数据类型(面向过程留下的痕迹,不过是对java的有益补充),Integer是一个类,是面向对象的体现,是int的扩展,定义了很多的转换方法,提供了处理int类型时非常有用的其他一些常量和方法。
即int是基本类型,不是类,为了符合面向对象编程,后来出现了Integer类,他是对int进行封装的。
2. 实现这种对象包装的目的主要是因为类能够提供必要的方法,用于实现基本数据类型的数值与可打印字符串之间的转换,以及一些其他的实用程序方法。
另外,有些数据结构库类只能操作对象,而不支持基本数据类型的变量,包装类提供一种便利的方式,能够把基本数据类型转换成等价的对象,从而可以利用数据结构库类进行处理。
3. int是基本的数据类型,Integer是int的封装类,int和Integer都可以表示某一个数值,int和Integer不能够互用,因为他们两种不同的数据类型。
如:
(1)
ArrayList al=new ArrayList();
int n=40;
Integer nI=new Integer(n);
al.add(n);//不可以
al.add(nI);//可以
(2)并且泛型定义时也不支持int: 如:
List<Integer> list = new ArrayList<Integer>();可以
而List<int> list = new ArrayList<int>();则不行。
(3)总而言之:如果我们定义一个int类型的数,只是用来进行一些加减乘除的运算or作为参数进行传递,那么就可以直接声明为int基本数据类型,但如果要像对象一样来进行处理,那么就要用Integer来声明一个对象,因为java是面向对象的语言,因此当声明为对象时能够提供很多对象间转换的方式与一些常用的方法。自认为java作为一门面向对象的语言,我们在声明一个变量时最好声明为对象格式,这样更有利于你对面向对象的理解。
4. 基本类型与包装类型的异同:
(1)在Java中,一切皆对象,但八大基本数据类型却不是对象。
(2)声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字。
(3)存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。
(4)初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0(整数:包括int,short,byte,long ,初始值为0),boolean类型为false,浮点型:float,double ,初始值为0.0,字符:char ,初始值为空格,即'' ",如果输出,在Console上是看不到效果的。
(5)使用方式的不同,比如与集合类合作使用时只能使用包装类型。
四、全面分析:Java基础之int和Integer有什么区别
1. int与integer的基本使用对比
int 是基本类型,直接存数值,进行初始化时int类的变量初始为0。
integer是对象,用一个引用指向这个对象,Integer的变量则初始化为null。如:
ArrayList al=new ArrayList();
int n=40;
Integer nI=new Integer(n);
al.add(n);//不可以
al.add(nI);//可以
2. Java两种数据类型分类
原始数据类型,分为boolean,byte,int,char,long,short,double,float
引用数据类型,分为数组,类,接口
3. Java为每个原始类型提供了封装类
为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每 一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
即:
原始类型: boolean, char, byte,short, int, long,float,double
封装类类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
4. 基本解析之自动装箱与自动拆箱
(1)自动装箱:将基本数据类型重新转化为对象
public class Test {
public static void main(String[] args) {
//声明一个Integer对象
Integer num = 9;
//以上的声明就是用到了自动的装箱:解析为:Integer num = new Integer(9);
}
}
9是属于基本数据类型的,原则上它是不能直接赋值给一个对象Integer的,但jdk1.5后你就可以进行这样的声明。自动将基本数据类型转化为对应的封装类型,成为一个对象以后就可以调用对象所声明的所有的方法。
(2)自动拆箱:将对象重新转化为基本数据类型
public class Test {
public static void main(String[] args) {
//声明一个Integer对象
Integer num = 9;
//进行计算时隐含的有自动拆箱
System.out.print(num--);
}
}
因为对象时不能直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除。
对比:
//装箱
Integer num = 10;
//拆箱
int num1 = num;
5. 深入解析
(1)情况描述:
public class Test {
public static void main(String[] args) {
//在-128~127 之外的数
Integer num1 = 128;
Integer num2 = 128;
System.out.println(num1==num2); //false
// 在-128~127 之内的数
Integer num3 = 9;
Integer num4 = 9;
System.out.println(num3==num4); //true
}
}
解析原因:归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)。
加大对简单数字的重利用,Java定义在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。
而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
(2)Integer源码解析:
给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,源码如下:
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
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);
}
五、补充见解:
1. 复杂类型(包装类型)和基本类型:
复杂类型和基本类型的内存模型本质上是不一样的,简单数据类型的存储原理是这样的:所有的简单数据类型不存在“引用”的概念,简单数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,而Java语言里面只有这八种数据类型是这种存储模型;而其他的只要是继承于Object类的复杂数据类型都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的。
2. Integer是int的封装类,里面有很多进行处理的静态方法。Integer是对象而int不是,内存的分配位置也不一样。Integer的属性和其他类一样的!在方法里都是引用传递,而int原始类型是值传递!
jdk1.5以后可以从int自动装箱Integer类。int是为了兼容以前的编程语言使用的基本类型,目的是让程序效率更高,以为它是直接分配到栈上的。所以它不是对象,不能有类似 int.operation()的操作。Integer是java中一切都是对象这个大前提下的int的包装类型,可以使用方法,是个对象,是用new分配到堆上的。
类的对象才能为null,不能把null赋值给一个变量。不能,如int m=null;但可以String s=null;因为String是个类。
本篇博文是小白我在大神的肩膀上,吸收整理出来的。衷心感谢大神们的无私奉献、厚薄积发的精神,这种品质给我们小白在技术上的成长带来了很大的帮助。
参考:
https://www.cnblogs.com/guodongdidi/p/6953217.html
https://blog.csdn.net/sunhuaqiang1/article/details/51958618
http://blog.csdn.net/chenliguan/article/details/53888018