Java 提供两种不一样的类型:引用类型和原始类型(或内置类型)。另外,Java 还为每一个原始类型提供了封装类(Wrapper)。若是须要一个整型变量,是使用基本的 int 型呢,仍是使用 Integer 类的一个对象呢?若是须要声明一个布尔类型,是使用基本的 boolean,仍是使用 Boolean 类的一个对象呢?本文可帮助您做出决定。java
下表列出了原始类型以及它们的对象封装类。程序员
原始类型 | 封装类 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long 数据结构 |
Long |
float | Float |
double | Double |
引用类型和原始类型的行为彻底不一样,而且它们具备不一样的语义。例如,假定一个方法中有两个局部变量,一个变量为 int 原始类型,另外一个变量是对一个 Integer 对象的对象引用:app
int i = 5; // 原始类型 Integer j = new Integer(10); // 对象引用
这两个变量都存储在局部变量表中,而且都是在 Java 操做数堆栈中操做的,但对它们的表示却彻底不一样。(本文中如下部分将用通用术语堆栈代替操做数堆栈或局部变量表。)原始类型 int 和对象引用各占堆栈的 32 位。(要表示一个 int 或一个对象引用,Java 虚拟机实现至少须要使用 32 位存储。)Integer 对象的堆栈项并非对象自己,而是一个对象引用。spa
Java 中的全部对象都要经过对象引用访问。对象引用是指向对象存储所在堆中的某个区域的指针。当声明一个原始类型时,就为类型自己声明了存储。指针
引用类型和原始类型具备不一样的特征和用法,它们包括:大小和速度问题,这种类型以哪一种类型的数据结构存储,当引用类型和原始类型用做某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。code
许多程序的代码将同时包含原始类型以及它们的对象封装。当检查它们是否相等时,同时使用这两种类型并了解它们如何正确相互做用和共存将成为问题。程序员必须了解这两种类型是如何工做和相互做用的,以免代码出错。orm
例如,不能对原始类型调用方法,但能够对对象调用方法:对象
int j = 5; j.hashCode(); // 错误 //。.. Integer i = new Integer(5); i.hashCode(); // 正确
使用原始类型无须调用 new,也无须建立对象。这节省了时间和空间。混合使用原始类型和对象也可能致使与赋值有关的意外结果。看起来没有错误的代码可能没法完成您但愿作的工做。例如:ci
import java.awt.Point; class Assign { public static void main(String args[]) { int a = 1; int b = 2; Point x = new Point(0,0); Point y = new Point(1,1); //1 System.out.println(“a is ” + a); System.out.println(“b is ” + b); System.out.println(“x is ” + x); System.out.println(“y is ” + y); System.out.println(“Performing assignment and ” + “setLocation.。.”); a = b; a++; x = y; //2 x.setLocation(5,5); //3 System.out.println(“a is ”+a); System.out.println(“b is ”+b); System.out.println(“x is ”+x); System.out.println(“y is ”+y); } }
这段代码生成如下输出:
a is 1 b is 2 x is java.awt.Point[x=0,y=0] y is java.awt.Point[x=1,y=1] Performing assignment and setLocation.。. a is 3 b is 2 x is java.awt.Point[x=5,y=5] y is java.awt.Point[x=5,y=5]
修改整数 a 和 b 的结果没什么意外的地方。b 的值被赋予整型变量 a,结果 a 的值增长了 1。这一输出反映了咱们但愿发生的状况。可是,使人感到意外的,是在赋值并调用 setLocation以后 x 和 y 对象的输出。咱们在完成 x = y 赋值以后特地对 x 调用了 setLocation,x 和 y 的值怎么会相同呢?咱们毕竟将 y 赋予 x,而后更改了 x,这与咱们对整数 a 和 b 进行的操做没什么不一样。
这种混淆是由原始类型和对象的使用形成的。赋值对这两种类型所起的做用没什么不一样。但它可能看起来全部不一样。赋值使等号 (=) 左边的值等于右边的值。这一点对于原始类型(如前面的 int a 和 b)是显而易见的。对于非原始类型(如 Point 对象),赋值修改的是对象引用,而不是对象自己。所以,在语句
x = y;
以后,x 等于 y。换句话说,由于 x 和 y 是对象引用,它们如今引用同一个对象。所以,对 x 所做的任何更改也会更改 y。下面是 //1 处的代码执行之后的状况:
执行 //2 处的赋值之后状况以下:
当在 //3 处调用 setLocation 时,这一方法是对 x 引用的对象执行的。由于 x 引用的 Point 对象也正是 y 所引用的对象,因此咱们如今获得如下结果:
由于 x 和 y 引用同一个对象,因此对 x 执行的全部方法与对 y 执行的方法都做用于同一个对象。
区分引用类型和原始类型并理解引用的语义是很重要的。若作不到这一点,则会使编写的代码没法完成预约工做。
但愿经过以上内容的介绍,可以给你带来帮助。
另外,引用类型的一些优点:
对象能够被序列化,原始类型不行。 对象提供的方法能够灵活转换,能够扩展,原始类型不行 在集合类中只能使用对象,不能使用原始类型 原始类型没有null的概念,对象有,某些状况下须要辨别某个参数是否被初始化了,若是使用原始类型,那么0的值不知道是初始值仍是没有初始化系统自动给的。 引用类型能够封装