什么是包装类

Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。例如java中的数据类型int,double等不是就对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。为了让基本类型也具有对象的特征,就出现了包装类型。Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

java为我们提供了基本数据类型的包装类,这些包装类分为两类,一种是对象型包装类,不继承任何其他类(Object的直接子类),另一种是数值型包装类,继承于Number类。八种包装类和基本数据类型的对应关系如表所示:

java 中包装类作用 java包装类有哪些_包装类

 在这八个类名中,除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已。

除了Character和Boolean以外,其他的都是“数值型”,“数值型”都是java.lang.Number的子类。Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。

包装类的用途

类的用途主要包含两种:

1. 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如Object[]、集合等的操作。

2. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!),通俗点说就是方便类型转换

java 中包装类作用 java包装类有哪些_java 中包装类作用_02

public class TestWrapped {

	public static void main(String[] args) {

		// 基本类型转化成Integer对象
		Integer b = Integer.valueOf(20); // 官方推荐这种写法
		
		//把包装类转化为基本数据类型
		int c = b.intValue();
		double d = b.doubleValue();
		
		//把字符串转化为类对象
		Integer e = new Integer("99999");
		Integer f = Integer.parseInt("9999");
		
		//把包装类对象转化为字符串
		String str1 = b.toString();
	}

}

其他包装类的用法类似。

自动装箱和拆箱

自动装箱:    基本数据类型------>对象

基本类型的数据处于需要对象的环境中时,会自动转为“对象”。

我们以Integer为例:在JDK1.5以后,Java提供了自动装箱的功能,因此只需Integer i = 5这样的语句就能实现基本数据类型转换成包装类,这是因为JVM为我们执行了Integer i = Integer.valueOf(5)这样的操作,这就是Java的自动装箱。

Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是valueOf(100),而不是new Integer(100)

自动拆箱:    对象--------->基本数据类型

 每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用intValue()、doubleValue()等转型方法。

 如 Integer i = 5;int j = i; 这样的过程就是自动拆箱。

Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();

我们可以用一句话总结自动装箱/拆箱:

自动装箱过程是通过调用包装类的valueOf()方法实现的,而自动拆箱过程是通过调用包装类的 xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)。

自动装箱与拆箱的功能事实上是编译器来帮的忙,编译器在编译时依据您所编写的语法,决定是否进行装箱或拆箱动作。

包装类的缓存问题

整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。

缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

例子:

public class Test3 {
    public static void main(String[] args) {
        Integer in1 = -128;
        Integer in2 = -128;
        System.out.println(in1 == in2);//true 因为123在缓存范围内
        System.out.println(in1.equals(in2));//true
        Integer in3 = 1234;
        Integer in4 = 1234;
        System.out.println(in3 == in4);//false 因为1234不在缓存范围内
        System.out.println(in3.equals(in4));//true
    }
}

在上面的这一段程序当中,in1为一个对象,值为-128,在-128~127之间,因此会进行缓存处理。

再定义一个in2之后,不会新分配地址,而是将in1的地址传给in2。

对于 == 而言,比较的是两个对象是否想等,因此输出的应该是true。

而使用equals()是判断其值是否相等,因此也是true。

接着定义in3对象的值为1234,它并不在-128~127之间,因此不是存储在缓冲区当中,再定义一个in4的时候会分配一个新的空间。

因此 in3 == in4 输出为false,而in3.equals(in4)输出为true。

java 中包装类作用 java包装类有哪些_基本数据类型_03

java 中包装类作用 java包装类有哪些_自动装箱_04