本人之所以把包装类作为单独一篇博文来写,主要是因为这里知识比较冗杂,为了帮助大家比较好的理解深层次的东西而不是做一个搬砖的这里我有必要单开一篇博文来了解下。
首先我们来分析一下基本数据类型和包装类:
- 包装类是对象,拥有方法和字段,对象的调用都是通过引用对象的地址;基本类型不是。
- 包装类型是引用的传递;基本类型是值的传递
- 声明方式不同:
基本数据类型不需要new关键字;
包装类型需要new在堆内存中进行new来分配内存空间 - 存储位置不同:
基本数据类型直接将值保存在值栈中;
包装类型是把对象放在堆中,然后通过对象的引用来调用他们 - 初始值不同:
int的初始值为 0 、 boolean的初始值为false
包装类型的初始值为null - 使用方式不同:
基本数据类型直接赋值使用就好;
包装类型是在集合如 coolectionMap时使用
包装类和基本数据类型有如下对应关系:
Integer对应 int
Byte 对应 byte
Short 对应 short
Long 对应 long
Float 对应float
Double 对应double
Boolean 对应boolean
Character 对应char
基本数据类型对应的包装类 包含了这些类型的基本操作,比如最大最小值,String转化为对应的值等。
String 转基本数据类型比如:
我现在想把string类型的"10"转化为int类型,那么请看如下截图以及代码:
可以看到integer下有许多的方法。
int b = Integer.parseInt("10");
System.out.println(b);
下面我们再来看一段代码:
int a = 10;
Integer b = 10;
这里可以看到这两段代码均没有报错,但是正如前文所提a是一个基本数据类型,我们当然可以给他直接赋值。但是作为Integer他是一个类,所以这里我们为什么也直接给一个封装好的类赋值呢?
这里就涉及到一个拆箱装箱的问题。
好下面我们一步一步的解决。首先我们为什么可以给Integer赋值呢,因为Integer中有一个valueOf()方法。我用的编译器是Eclipse,如果你也用的是Eclipse那就按住ctrl键再单击代码中的Integer。找到以int为参数的valueOf方法。下面我截图给大家:
当你直接给Integer类型的变量赋值的时候Integer对象会自动调用这个方法进行装箱。
下面我们在来写一段代码我们看一下a和b是否相等。
int a = 10;
Integer b = 10;
System.out.println(a==b);
看下结果:
好,下面我们把数字放大些:
int a = 1000;
Integer b = 1000;
System.out.println(a==b);
没错结果依然为真。
下面我们再换如下代码进行实验:
Integer a = 10;
Integer b = 10;
System.out.println(a==b);
大家不妨先猜测一下真假,首先上两个例子的代码是一个int和一个integer,当我们给他们两个直接赋值时候会涉及到一个自动拆箱装箱的问题就是自动在int和integer之间转换,好了不磨叽了我们来看结果:
你没有看错依然为true。可能到这里会有人有疑问感觉我说了半天等于没说,请稍安勿躁,记住慢慢来,比较快。
我们再来给一个大一些的值:
Integer a = 1000;
Integer b = 1000;
System.out.println(a==b);
这次就出现了诸位一直在期待的false。
为什么:我来解释一下
对于对象,引用类型,"=="比较的是对象的内存地址这一点请务必清楚,下面稍微有些复杂了,我们再来看一下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是一个数组,其范围是-127到128当我们没有逾越这个范围的,所以当我们赋值其中的值的时候,如果没有逾越这个范围,那么它是会直接从数组中取值,而不会在堆中再开辟一个内存。所以这个时候我们赋值为10的时候是可以比较的。但是当我们赋值为1000的时候,我们再看上面那段代码,已经不能再满足if的条件。所以它直接又返回了new了一个新的东西。所以等于是在内存中又开辟了两个空间,比如一个位置是0x20031,另一个是0x20032。所以自然就不相等了。