Java之包装类【一篇搞定】

包装类

Java中有八种基本数据类型,它们只能表示一些最简单的数字,这些数字最小的在内存中占1个字节8位,最大占8个字节64位。这些都是简单的数字,不是对象,所以不能用来调用方法或者属性,功能不够强大。

1 概述

针对这八种基本类型,JavaAPI又专门提供了对应的类类型,目的就是为了分别把这八种基本类型的数据,包装成对应的类类型,这时候就变成对象了,就可以调用方法了或者访问属性了。

基本类型包装类型
booleanjava.lang.Boolean
bytejava.lang.Byte
shortjava.lang.Short
intjava.lang.Integer
longjava.lang.Long
floatjava.lang.Float
doublejava.lang.Double
charjava.lang.Character

2 基础案例

在这些包装类型中,都定义相关的属性和方法,例如Integer中:

package com.briup.chap07.test;

public class Test042_Integer {
	public static void main(String[] args) {
		 int i = 1;
        //编译报错,因为i不是对象
        //i.toString();

        //1.int --> Integer
        //Integer o = new Integer(i);
        Integer o = Integer.valueOf(1);

        //2.Integer --> int
        int j = o.intValue();

        System.out.println(o.toString());

        //3.包装类静态成员访问
        System.out.println(Integer.MIN_VALUE);
        System.out.println(Integer.MAX_VALUE);

        //4.包装类静态方法调用
        //把100分别转为十进制、二进制、八进制、十六进制的字符串形式
        System.out.println(Integer.toString(100));
        System.out.println(Integer.toString(100,2));
        System.out.println(Integer.toString(100,8));
        System.out.println(Integer.toString(100,16));

        //把100转为二进制形式
        System.out.println(Integer.toBinaryString(100));

        //把字符串"100"转为int类型的100
        int num = Integer.parseInt("100");
        System.out.println(num);
	}
}

注意:一定要掌握 public static int parseInt(String s)方法。

3 装箱拆箱

JDK1.5或以上,可以支持基本类型和包装类型之间的自动装箱、自动拆箱,这简化了基本类型和包装类型之间的转换。

  • **自动装箱:**基本数据类型值 自动转化为 包装类对象

  • **自动拆箱:**包装类对象 自动转化为 基本数据类型值

案例展示:

​ int、Integer自动装箱拆箱展示。

package com.briup.chap07.test;

public class Test043_Integer {
	public static void main(String[] args) {
		//JKD1.5 之前
		//Integer o = new Integer(1);
		//Integer o = Integer.valueOf(1);

		//JDK1.5 之后
		//自动装箱,这里会自动把数字1包装成Integer类型的对象
		Integer o = 1;

		//JKD1.5 之前
		//Integer o = new Integer(1);
		//int i = o.intValue();


		//JDK1.5 之后
		//Integer o = new Integer(1);
		//自动拆箱,这里会自动把对象o拆箱为一个int类型的数字,并把数字赋值给int类型的变量i
		int i = o;
	}
}

其他的基本类型和包装类型之间的转换,与此类似。

注意事项:

​ 不同类型的基本数据类型和包装类,是不可以自动装箱拆箱的,例如int和Long;

​ 给Byte Short Character赋值时,需要考虑 常量优化机制。

具体案例如下:

package com.briup.chap07.test;

public class Test043_Test {
	public void test1(int i) {
	}
    
	public void test2(Integer i) {
	}
    
	public void test3(long i) {
	}
    
	public void test4(Long i) {
	}

    //不同类型的基本数据类型和包装类,不可以自动装箱拆箱
	public static void main01(String[] args) {
		Test043_Test t=new Test043_Test();
		t.test1(1);// 编译通过 int i = 1; 正常赋值
		t.test2(1);// 编译通过 Integer i = 1; 自动装箱
		t.test3(1);// 编译通过 long i = 1; 隐式类型转换

		// 编译报错
		// 错误的代码:Long i = 1;
		// int和Long 之间没有任何关系
		//t.test4(1);

		t.test4(1L);// 编译通过 Long i = 1L; 自动装箱
	}
    
    public static void main(String[] args) {
        //注意: 自动装箱时候 要保证类型一致
        //Long l = 2; ERROR
        Long l2 = 23L;
        //int t = l2; ERROR
        long t = l2;

        //给Byte Short Character赋值时,需要考虑 常量优化机制
        Byte b1 = 2;
        Byte b2 = 127;
        //Byte b3 = 128;  ERROR

        Character c1 = 3;
        Character c2 = '\u0989';
        Character c3 = 65535;
        //Character c4 = 65536;   ERROR
    }
}

4 Integer缓冲区

常见面试题:分析下面程序的输出结果。

public static void main(String[] args) {
    Integer i1 = new Integer(127);
    Integer i2 = new Integer(127);
    System.out.println("i1 == i2: "+ (i1 == i2));	//?

    Integer i3 = 127;
    Integer i4 = 127;
    System.out.println("i3 == i4: "+ (i3 == i4));	//?

    Integer i5 = 128;
    Integer i6 = 128;
    System.out.println("i5 == i6: "+ (i5 == i6));	//?
}

//程序的输出结果为:
i1 == i2: false
i3 == i4: true
i5 == i6: false

在Java中方法区有一个叫做**运行时常量池(Runtime Constant Pool)**的区域,用于存储编译期间生成的各种字面量和符号引用,Integer常量池就存储在该区域。

Integer常量池是一个特殊的缓存机制,用于存储在范围[-128, 127]之间的Integer常量对象。这个范围是Java中的一个固定范围,超出这个范围的整型常量不会被缓存。

当使用**自动装箱(Autoboxing)**将一个整数赋值给一个Integer对象时,如果该整数在[-128, 127]范围内,那么会从Integer常量池中获取一个已经存在的对象,而不是创建一个新的对象。这是因为在这个范围内的整数常见且频繁使用,通过复用对象可以节省内存空间和提高性能

Integer对象内存构成:
在这里插入图片描述

结果分析:

i1 == i2 结果为false,图上很清楚,无需多解释。

i3 == i4 结果为true,因为127在[-128,127]这个范围中,i3和i4直接复用了常量池中Integer(127)对象,故而两者哈希码值相同,== 比较也相同。

i5 == i6 结果为false,因为128不在[-128,127]这个范围中,i5和i6自动装箱过程中,系统底层执行了Integer i5 = new Integer(128); Integer i6 = new Integer(128);,故而i5和i6指向2个不同的对象。

Integer源码分析:

package java.lang;

public final class Integer extends Number implements Comparable<Integer> {
	//省略...
    
    /**
     * Cache to support the object identity semantics of autoboxing for values between 128 and 127 (inclusive) as required by JLS.
     */
	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;
            
            // 省略... 
            
            high = h;

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

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }
    
    //省略...
}

补充内容:

System类方法:

public static native int identityHashCode(Object x);

该方法会返回对象的哈希码,即Java根据对象在内存中的地址计算出来一个整数值,结论:相同地址的对象调用该方法结果相同,不同地址对象结果不同!

注意,哈希码并不是对象的内存地址。

验证案例:

package com.briup.chap07.test;

public class Test044_Cache {
	public static void main(String[] args) {
		Integer i1 = new Integer(127);
		Integer i2 = new Integer(127);
		System.out.println("i1: " + System.identityHashCode(i1));
		System.out.println("i2: " + System.identityHashCode(i2));
		System.out.println("i1 == i2: "+ (i1 == i2));	//false
		
		System.out.println("--------------");
		
		Integer i3 = 127;
		Integer i4 = 127;
		System.out.println("i3: " + System.identityHashCode(i3));
		System.out.println("i4: " + System.identityHashCode(i4));
		System.out.println("i1 == i3: "+ (i1 == i3));	//false
		System.out.println("i3 == i4: "+ (i3 == i4));	//true
		
		System.out.println("--------------");

		Integer i5 = 128;
		Integer i6 = 128;
		System.out.println("i5: " + System.identityHashCode(i5));
		System.out.println("i6: " + System.identityHashCode(i6));
		System.out.println("i5 == i6: "+ (i5 == i6));	//false
	}
}

运行效果:
在这里插入图片描述

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值