在Java中, 所有要处理的东西几乎都是对象 (Object)
在 Java SE 5.0之后提供了自动装箱的功能,可以直接使用以下语句来打包基本数据类型:Integer integer = 10;
在进行编译时,编译器会判断是否进行自动装箱动作。自动装箱适用于 boolean、byte、short、char、long、float、double等基本数据类型,会使用对应的打包类型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。
public class AutoBox {
public static void main(String[] args) {
Integer a = 1;//int类型自动装箱
System.out.println(a + 1);//Integer自动拆箱
}
}
装箱中如果数字为1个字节内(-128~127),则会将这个数字放入缓存池中,创建对象时返回该对象的引用,这涉及到了Java的享元模式(Flyweigth)
public class AutoBoxFlyweigth {
public static void main(String[] args) {
Integer a = 12;
Integer b = 12;
System.out.println(a == b);// true
Integer c = 1234;
Integer d = 1234;
System.out.println(c == d);// false
Integer e = new Integer(13);
Integer f = new Integer(13);
System.out.println(e == f); //false
Integer g = new Integer(1200);
Integer h = new Integer(1200);
System.out.println(g == h); //false
}
}
通过Java源代码可以看到Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256,Integer类中还有一个Static Block(静态块)。从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer a=12时,JVM会直接在该在对象池找到该值的引用。也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有没有12的对象,如果有直接返回该对象的引用;如果没有,则使用new一个对象,并返回该对象的引用地址。因为Java中“==”比较的是两个对象的引用(即内存地址),a、b为同一个对象,所以结果为true,因为1234超过了Integer缓存数据范围,使用new方式创建:c = new Integer(1234);d=new Integer(40);虽然他们值相等,但是属于不同的对象,不会被放到对象池中,所以他们不是同一个引用,返回false。
用一句简短通俗的话话概括享元模式:
如果有很多个小的对象,它们有很多属性相同,那可以把它们变成一个对象,那些不同的属性把它们变成方法的参数,称之为外部状态,相同的属性称之为内部状态,这种机制即为享元模式。
int (-128,127) 范围的处理 和 String s= "a"; 类似 //从缓存池中取,如果没有在在池中和堆上创建
String s = new String("ss"); //直接在堆上创建