java基础数据类型自动装箱拆箱

java基础数据类型自动装箱拆箱

 

一、定义:

public class test {
    public static void main(String[] args) {
        Integer a = 3;//装箱
        int b = a;//拆箱
    }
}

 查看Integer的源码,可知:

基础类型的包装类,装箱,实际调用的是包装类的valueof方法;

拆箱,调用的是包装类的:xxxValue方法;

比如对于Integer,装箱:Integer.valueOf(int i);拆箱:Integer.intValue()

 

二、运用举例及坑:

 

1、运用举例代码:

public class TestAutoBoxing {

	/**
	 * 测试类演示基础类型的自动装箱和拆箱,及比较规则
	 * @author cdzhujun
	 */
	public static void main(String[] args) {
		/**
		 * 在-128~127 之内的数,如果已经有了,则会缓存,支持复用 类似类型还有:Short/Character/Long/Byte
		 * 取值范围: Integer,Byte,Short,Long:[-128,127] Character:[0,127]
		 * Float,Double:没有缓存,每次都new一个新的 Boolean:只有两个固定值,只要值一样就相等
		 */
		System.out.println("############################");
		// 在-128~127 之外的数
		Integer ii1 = 200;
		Integer ii2 = 200;
		System.out.println("ii1==ii2: " + (ii1 == ii2));// false
		// 在-128~127 之内的数
		Integer ii3 = 100;
		Integer ii4 = 100;
		System.out.println("i3==i4: " + (ii3 == ii4));// true
		System.out.println("—————————");

		Double d1 = 100.0;
		Double d2 = 100.0;
		Double d3 = 200.0;
		Double d4 = 200.0;
		System.out.println(d1 == d2); // false
		System.out.println(d3 == d4); // false
		System.out.println("—————————");

		Boolean b1 = false;
		Boolean b2 = false;
		Boolean b3 = true;
		Boolean b4 = true;
		System.out.println(b1 == b2);// true
		System.out.println(b3 == b4);// true
		System.out.println("—————————");
		
		/**
		 * ==比较:
		 * 都为基础类型时,比较的是值;都为包装类时,按缓存规则比较;基础类和包装类比较,包装类会自动拆箱
		 * new就不说了,每次new,都在堆内存中新建一个对象
		 */
		System.out.println("############################");
		// Example 1: 都为基础类型时,比较的是值
        int i1 = 1;
        int i2 = 1;
        System.out.println("i1==i2 : " + (i1 == i2)); // true
        // Example 2: 都为包装类时,按缓存规则比较
        Integer obj1 = 1; 
        Integer obj2 = 1; 
        System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true
        // Example 3: 基础类和包装类比较,包装类会自动拆箱
        Integer num1 = 1; 
        int num2 = 1;
        System.out.println("num1 == num2 : " + (num1 == num2)); // true
        // Example 4: new就不说了,每次new,都在堆内存中新建一个对象
        Integer one = new Integer(1); 
        Integer anotherOne = new Integer(1);
        System.out.println("one == anotherOne : " + (one == anotherOne)); // false
        // Example 5: 一个是包装类,一个是new出来的,也相当于两个new
        System.out.println(num1 == one); // false
        
        /**
         * ==的特殊场景:
         * 1、如果==号比较的其中一个为表达式(以+、-、*、/、>、<运算符运算的,包装类先拆包参与运算
         * 2、当 ==运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象;
         * 而如果其中有一个操作数是表达式(即包含算术运算),则比较的是数值(即会触发自动拆箱的过程)。
         */
        System.out.println("############################");
        Integer num111 = 100;  
        int num222 = 100;  
        Long num333 = 200L;
        long numm3 = 100L;
        Integer numm1 = 200;
        //num111先拆箱参与运算,num111+num222运算后为int类型,然后在装箱变为Integer
        //由于右侧的操作是包含表达式,故最终num333和(num111 + num222)计算的结果会自动拆箱,变成long与int类型
        //long/int基础类型是可以进行==比较的,比较的仅仅是值,故最终结果返回true
        System.out.println(num333 == (num111 + num222)); //true
        System.out.println(num222 == numm3); //true
        //System.out.println(num333 == numm1);//这样写是不行的,应为类型不匹配
        
        /**
         * 包装类的equals():类型相同,且变量的值相等,才会最终返回true
         * 注意:包装类的equals()方法重写了Object类的相同方法;
         * 而String、Date类亦重写了Object类equals(),只是实现不一样(不在这里讨论)
         */
        System.out.println("############################");
        Integer num11 = 100;  
        int num22 = 100;
        Long num4 = 200L;
        System.out.println(num11.equals(num22));  //true
        System.out.println(num4.equals(num11 + num22)); //false,因为equals不拆箱,因Long与Integer类型不匹配
        System.out.println(num4 == (num11 + num22)); // true,有操作符,+计算结果会拆箱
	}

}

 2、坑Integer类型可以为nullint类型不能为null

Integer i1=null;
int i2=i1;

 这两行代码是完全合法的,完全能够通过编译的,但是在运行时,就会抛出空指针异常,因为int类型不能为null

所以:在自动拆箱时,要保证包装类的值不能为null

 

三、自动装箱拆箱的优点及弊端:

1、优点:

省事, 简化代码。自动把基础类型和包装类互转。

节约内存。如上面的例子,在数字范围比较小时,可复用类的对象( [-128,127] )。

 

2、弊端:在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum+=i;
}

 内部实际为:

sum = sum.intValue() + i;
Integer sum = new Integer(result);

 new了很多个对象出来,但没实际用处,故会增加外内存开销,影响性能。

 

四、基本类型与包装类型的异同

 

1、在Java中,一切皆对象,但八大基本类型(char,byte,int,double,float,short,long,boolean)却不是对象

       2声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字。

       3存储方式及位置的不同,基本类型是直接存储变量的值保存在栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。

       4初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0(整数:包括int,short,byte,long ,初始值为0)boolean类型为false,浮点型:float,double ,初始值为0.0,字符:char ,初始值为空格,即'' ",如果输出,在Console上是看不到效果的。

       5使用方式的不同,比如与集合类合作使用时只能使用包装类型。

 

 

猜你喜欢

转载自pigcircle-126-com.iteye.com/blog/2397754