java的自动装箱和自动折箱
包装类(wrapper)和基本类型(primitive)
- 基本类型: byte,short,char,int,long,float,double,boolean
- 包装类为: Byte,Short,Character,Integer,Long,Float,Double,Boolean
自动装箱和自动折箱
- 自动装箱: 基本类型转成包装类的过程,通过调用包装类的
valueOf()
方法 - 自动折箱: 包装类转成基本类型的过程,通过调用包装类的
intValue(),doubleValue(),*Value()
对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值 。
Integer a = 23; //自动装箱,相当于 Integer a = Integer.valueOf(23);
int b = a; //自动折箱, 相当于 int b = a.intValue();
经典的问题
@Test
public void integerTest(){
Integer a=10;
Integer b=10;
Integer c=1000;
Integer d=1000;
System.out.println("a==b ? : "+ (a==b));
System.out.println("c==d ? : "+ (c==d));
}
//结果
a == b ? : true
c == d ? : false
分析: 首先a==b
和c==d
比较的是引用;然后a,b,c,d都发生了自动装箱的操作,必然会调用Integer.valueOf()
方法,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);
}
可以发现: Integer使用IntegerReference
缓存了-128~127
之间的值:
- 如果i在
-128~127
之间,取出的是同一个对象 - 如果i不在
-128~127
之间,会重新new一个对象
包装类引用传递
有些人认为包装器类可以用来实现修改数值参数的方法 , 然而这是错误的
public void changeFun(int x){ //没有效果
x = x+3;
}
//再或者
public void changeFun(Integer x){ //也没有效果
x = 12;
// x = new Integer("21");
}
问题是Integer对象是不可变的:包含在包装器中的内容不会改变:不能使用这些包 装器类创建修改数值参数的方法如果想编写一个修改数值参数值的方法,就需要使用在 org.omg.CORBA包中定义的持有者(holder)类型,包括 IntHolder、BooleanHolder等
如:
public void changeFun (IntHolder x ){
x.value = 10 * x.value;
}
或者是自定义实体类,可以通过自定义实体类的setter方法设值
//PlainString.java
public class PlainString {
private String value;
public PlainString(String value) {
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}
public void changeFun (PlainString ps){
ps.setValue(3);
}