您的位置:首页 > 其它

5. 原生类型与封箱类

2016-12-18 19:27 183 查看

原生类型与封箱类

八个原生数据类型与void,与他们的箱

byte Byte
short Short
char Character
int Integer
float Float
long Long
double Double

boolean Boolean

void Void

在jdk的原码中,可以找到
Class.getPrimitiveClass
一共在九个地方使用过,正好是上面的九个类型。前八个是数据原生类型,后面的void一般用不到。对应的叫他们的封装类型,也可以叫他们是
,而原生与箱之间的转换分别叫做
封箱
拆箱


出现的场景

int a1 = new Integer(10); //拆箱, 拆了new Integer(10)的箱成int类型,对应Integer.inValue();
Integer a2 = 100; //封箱,封了100的箱成Integer类,对应Integer.valueOf(…)

相关的操作由编译器来完成,这可以用javap来反编译查看,具体可以查看这片文章
封箱与拆箱之间,会造成损耗,可以看看这篇文章

封装类

Boolean只有两个值,true与false,所以内部代码也简单。

public class Mutax {
public static void main(String[] args) {
Boolean a1 = true;   //封箱。调用Boolean.valueOf(true)方法,在方法中返回的是Boolean.True;
Boolean a2 = true;   //封箱。同样是调用Boolean.valueOf(true)方法,所以返回对象是一样的
Boolean a3 = new Boolean(true); //不是Boolean.True,虽然也是true;
boolean a4 = true;
boolean a5 = new Boolean(true); //拆箱,为true值。

System.out.println(a1 == a2);   // 对象相同,true
System.out.println(a1 == a3);   // 对象不同,false
System.out.println(a1 == Boolean.TRUE); //对象相同,true

System.out.println(a3 == a4);   // a4为原生类型,a4拆箱。true;
System.out.println(a3 == a5);   // a5已经是拆箱之后的原生类型,所以也是true;
}
}

Character是操作字符集,utf-8中还包括汉字等,在其中汉字对应的
UnicodeBlock
CJK,CJK是Chinese、Japanese、Korean三个国家的文字。Character内部类CharacterCache中有128个缓存,所以也会出现大家都知道的类似Integer的缓存效果。

public class Malix {
public static void main(String[] args) {
Character c1 = 127; //封箱,Character.valueOf(),因为小于128,所以会调用内部缓存中的数据
Character c2 = 127; //封箱,同上
Character c3 = 129; //封箱,大于128,不会调用缓存
Character c4 = 129; //同上
System.out.println(c1 == c2);  //true
System.out.println(c3 == c4);  //false
}
}

因为是对utf-8字符集操作,会有些想不到的效果。

public class Kalax {
public static void main(String[] args) {
System.out.println(Character.isDigit('1'));
System.out.println(Character.isDigit(1));
System.out.println(Character.isDigit(53));
}
}

结果分别是true,false,true。
为什么?1不是数字反而53是?因为53的ascii码中对应5,utf-8兼容着ascii,所以出现这种结果。

Byte、Short、Integer、Long、Float、Double为数值类型,继承了Number抽象类。

public abstract class Number implements java.io.Serializable {
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() { return (byte)intValue();}
public short shortValue() { return (short)intValue();}

}

所以这六个类中都可以转其他类。而他们拆箱的时候,调用的就是对应的方法。
六个类中,都有缓存128个缓存,但是Integer与其他不同

private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];

static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}

private IntegerCache() {}
}

可以通过
-XX:AutoBoxCacheMax=300
来修改Integer中的缓存大小,如果加上了这个参数,下面的程序结果就不一样了

public class Intex {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;

System.out.println(i1 == i2);// true
System.out.println(i3 == i4);//加上-XX:AutoBoxCacheMax=300就是true,不加就是false
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: