在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference Type(引用类型)。基本类型的数值不是对象,不能调用对象的toString()、hashCode()、getClass()、equals()等方法。所以Java提供了针对每种基本类型的包装类型。如下:
那么你可能会问Boolean占多少字节呢?
虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。
在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。这样我们可以得出boolean类型占了单独使用是4个字节,在数组中又是1个字节。使用int的原因是,对于当下32位的处理器(CPU)来说,一次处理数据是32位(这里不是指的是32/64位系统,而是指CPU硬件层面),具有高效存取的特点。
Java 1.5提供了自动装箱和拆箱的功能
装箱:值类型——引用类型,系统会在托管堆中生成一份堆栈中值类型对象的副本。
拆箱:引用类型——值类型,从托管堆中将引用类型所指向的已装箱数据复制会值类型对象。
<span style="font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:14px;">lass Program
{
static void Main(string[] args)
{
//首先定义一个值类型
int i = 3;
//装箱操作,因为要往箱子里装,所以先分配好一块内存来放这个数据也就是o
object o = i;
//拆箱操作
int y = (int)o;
}
} </span></span>
装箱的操作分为三步:
(1)内存分配:在托管堆中分配好内存空间以存放复制的实际数据。
(2)完成实际数据的复制:将值类型实例的实际数据复制到新分配的内存中。
(3)地址返回:将托管堆中的对象地址返回给引用类型变量。
但是拆箱和装箱的操作对于系统性能是一次巨大的挑衅,因为仅仅一个装箱的操作就分了这么多步骤,两个过程都要进行数据的复制,一个系统要拆装个好些回,还不得慢死啊。而且在这个过程中会产生多个不必要的对象,导致了系统性能的降低。所以为了避免拆装箱的操作,我们最好使用泛型来进行编程。但是有时候我们还是使用封装类更方便。
既然提供了基本类型,为什么还要使用封装类呢?
· 某些情况下,数据必须作为对象出现,此时必须使用封装类来将简单类型封装成对象。
1. 比如,如果想使用List来保存数值,由于List中只能添加对象,因此我们需要将数据封装到封装类中再加入List。在JDK5.0以后可以自动封包,可以简写成list.add(1)的形式,但添加的数据依然是封装后的对象。
2. 另外,有些情况下,我们也会编写诸如func(Object o)的这种方法,它可以接受所有类型的对象数据,但对于简单数据类型,我们则必须使用封装类的对象。
3. 某些情况下,使用封装类使我们可以更加方便的操作数据。比如封装类具有一些基本类型不具备的方法,比如valueOf(), toString(), 以及方便的返回各种类型数据的方法,如Integer的shortValue(), longValue(), intValue()等。
基本数据类型与其对应的封装类由于本质的不同,具有一些区别:
· 基本数据类型只能按值传递,而封装类按引用传递。
· 基本类型在堆栈中创建;而对于对象类型,对象在堆中创建,对象的引用在堆栈中创建。基本类型由于在堆栈中,效率会比较高,但是可能会存在内存泄漏的问题。