java中的包装类
java中有八种基本数据类型,对应的有八种包装类。他们分别是
- Byte;
- Short ;
- Character;
- Integer;
- Long;
- Float;
- Double;
- Boolean;
他们属于引用数据类型,有自己的方法和属性,内容比基本数据类型更加丰富。
并且他们的默认值是null。默认值为null的好处是,当你实体与数据库数据映射时,或者序列化或者反序列化时,你能清楚的知道这个属性是有值还是没值。不像基本数据类型有默认值。
不同版本下的包装类
在低版本中(我这里是用的jdk1.4。1.5有了自动拆装箱),包装类不能直接赋值,且包装类和基本数据类型不能互相比较的。
你必须强转,或者用new来生成包装类。且用==比较时,必须都转换为包装类或者基本数据类型,包装类变基本数据类型叫做拆箱,反之叫做装箱。这里1.4的Integer的valueof没有参数为int的,所以我先转为String。
下面我把jdk换成1.5
很明显,这样编译是通过的,因为当你执行Integer b1=10时,其实是执行这样的Integer b1=Integer.valueOf(10)语句。并且包装类和基本数据类型比较时,会自动完成上面所说的拆箱。
包装类与基本数据类型比较
看一下下面的代码,思考一下结果。
public static void main(String[] args) {
Integer a1= 10;
Integer a2= 128;
Integer a3= 10;
Integer a4= 128;
Integer b1=new Integer(10);
Integer b2=new Integer(128);
int c1=10;
int c2=128;
System.out.println(a1==b1);
System.out.println(a2==b2);
System.out.println("----------------");
System.out.println(b1==c1);
System.out.println(b2==c2);
System.out.println("----------------");
System.out.println(a1==a3);
System.out.println(a2==a4);
System.out.println("----------------");
System.out.println(a1==c1);
System.out.println(a2==c2);
System.out.println(c1==a1);
System.out.println(c2==a2);
}
下面是输出的结果:
前两个false很好理解,==是比较地址,两个Integer是不同的对象,所以不相等输出false.
然后第二组结果输出两个true是因为,包装类和基本数据类型比较会把包装类转换基本数据类型,比较的其实是值。这和第四组输出的四个true要表达的意思相同,我把第四组的比较的值位置替换再比较,是测试是否会将基本数据转换为包装类再比较,答案是否定的。他们之间比较只会是包装类拆箱。
第三组输出true和false这是为什么了?我前面说Integer b1=10时,其实是执行这样的Integer b1=Integer.valueOf(10),那我们来看一下这个valueof方法。
public static Integer valueOf(int var0) {
return var0 >= -128 && var0 <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[var0 + 128] : new Integer(var0);
}
这个方法的意思是,当你的参数大于等于-128且小于这个缓存池的high时,我就从这个池子里面拿值,否则我就新建一个Integer对象。我们再来看一下这个缓存池是个什么东西。
private static class IntegerCache {
static final int high;
static final Integer[] cache;
private IntegerCache() {
}
static {
int var1 = 127;
int var2;
if (Integer.integerCacheHighPropValue != null) {
var2 = Long.decode(Integer.integerCacheHighPropValue).intValue();
var2 = Math.max(var2, 127);
var1 = Math.min(var2, 2147483519);
}
high = var1;
cache = new Integer[high - -128 + 1];
var2 = -128;
for(int var3 = 0; var3 < cache.length; ++var3) {
cache[var3] = new Integer(var2++);
}
}
}
这是Integer中的静态内部类,Integer[] cache是一个Integer的数组,里面放了值为-128到high的Integer对象。high等于127。
所以说,你用valueof获得的Integer只要参数在-128到127之间,你都是从池子里面拿的,参数相同的话,拿的是同一个对象。
对应的byte,short,char,long的包装类也有缓存池。
版本往上走,对应的valueof和cache的代码有些不同,但效果还是一样。
然后我这里有个问题想求救一下
左边是我的编译前的代码,右边是我用·idea打开的class文件,为什么我的Integer a2=10没有使用valueof,但是给它赋值另一个变量时就会使用。但是Short又会,这是个什么情况。还有比较时也没有拆箱,按道理是会拆箱的。就是我想看反编译的结果该怎么操作啊,我在idea里面下的是jad那个插件。
补充:
如果你想看实际执行的代码,是否有语法糖,还有一种办法,就是用javap -c class文件去查看字节码。不过首先你得手动执行javac命令,下面是java文件中的代码
public class packaging {
public static void main(String[] args) {
Integer a=1;
int b=1;
System.out.println(a==b);
}
然后在终端去执行命令
去看字节码旁边的注释,确实是使用了valueof和拆箱intValue的。