当前位置: 首页 > 图灵资讯 > 技术篇> Java中区分引用类型和原始类型

Java中区分引用类型和原始类型

来源:图灵教育
时间:2024-03-01 15:57:35

下表列出了原始类型及其对象包装类型。

原始类型和包装类型 原始类型 封装类 boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double

引用类型与原始类型的行为完全不同,具有不同的语义。例如,假设一种方法中有两个局部变量,一个变量是 int 原始类型,另一个变量是一个 Integer 对象对象引用:

int i = 5; // 原始类型 Integer j = new Integer(10); // 对象引用

这两个变量都存储在局部变量表中,都存储在 Java 在堆栈中操作,但对它们的表达却完全不同。(以下部分将用通用术语堆栈代替操作数堆栈或局部变量表。)原始类型 int 对象引用各占堆栈的对象 32 位。(表示一个 int 或引用一个对象,Java 虚拟机至少需要使用 32 位存储。)Integer 对象的堆栈项不是对象本身,而是对象的引用。

Java 所有对象都必须通过对象引用访问。对象引用是指向对象存储堆中某一区域的指针。当声明原始类型时,声明存储类型本身。前两行代码表示如下:

引用类型和原始类型具有不同的特征和用法,包括:大小和速度问题,当引用类型和原始类型用作某一类别的实例数据时,该类型的数据结构存储指定的缺失值。对象引用实例变量的缺失值为 null,原型实例变量的缺失值与其类型有关。

许多程序代码将包含原始类型和对象包装。当检查它们是否相等时,使用这两种类型并了解它们如何正确地相互作用和共存将成为一个问题。程序员必须了解这两种类型是如何工作和相互作用的,以避免代码错误。

例如,不能调用原始类型的方法,但可以调用对象的方法:

int j = 5; j.hashCode(); // 错误 //... Integer i = new Integer(5); i.hashCode(); // 正确

无需调用原始类型 new,没有必要创建对象。这节省了时间和空间。原始类型和对象的混合使用也可能导致与赋值相关的意想不到的结果。似乎没有错误的代码可能无法完成你想做的事情。例如:

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 所有执行方法都作用于同一对象。

区分引用类型和原始类型,理解引用的语义是非常重要的。如果不这样做,编写的代码将无法完成预定工作。