我爱电脑技术论坛's Archiver

黑侠 发表于 2008-5-14 09:33

Java编程入门:引用类型和原始类型的区分

Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。另外,Java 还为每个原始类型提供了封装类(Wrapper)。如果需要一个整型变量,是使用基本的 int 型呢,还是使用 Integer 类的一个对象呢?如果需要声明一个布尔类型,是使用基本的 boolean,还是使用 Boolean 类的一个对象呢?本文可帮助您作出决定。
%fT0t*fc G o5h
kxL.W-b%c-a;Bg 1PRJ-z;@(@
下表列出了原始类型以及它们的对象封装类。 stvo\V

%Y-E}n${u
_!tI CK1w*~ Z 原始类型 封装类 T|,UI2v-b!G*Mm

]~:E@i:[K =================
8Af"t*]5k2Q)r~
I1L*KX e.zI!h z boolean Boolean $Z w(F-p$USP Y,`

3k$? O*z pG!u2D.P char Character
u-C i],T1P+@'L:M
N(j:@.n3O%]rYJz byte Byte
y7xJd5Q@ sDE
])Q2j'YtU$c&Ey short Short
mGN)Z dI[9f
N q6Q4t'g0L~\E)C int Integer
Z`.D5B"W HX*~wJ hcz]vI~'] B?U
long Long AC*d6hz!{

:?K n!~ S5P&P float Float
lB&Zr h,F BTS.IVO5q
double Double
2A9`@ rKF0e;x
$Wep a9{Y
H'e7\xU4o6XxW 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。例如,假定一个方法中有两个局部变量,一个变量为 int 原始类型,另一个变量是对一个 Integer 对象的对象引用:
%V%~3M "u&O!X!Y&UF;oE
"Ns%Zot

'E;gk,q%Mf[9tO.a ? int i = 5; // 原始类型 2mtJ3T6`P\&W

#[8WN mjG/G Integer j = new Integer(10); // 对象引用 if2`yUB
r rrZg2V
6mi yb:b+j#bm
7}eNc\6h:q
Zn&b*{3F)|(K
这两个变量都存储在局部变量表中,并且都是在 Java 操作数堆栈中操作的,但对它们的表示却完全不同。(本文中以下部分将用通用术语堆栈代替操作数堆栈或局部变量表。)原始类型 int 和对象引用各占堆栈的 32 位。(要表示一个 int 或一个对象引用,Java 虚拟机实现至少需要使用 32 位存储。)Integer 对象的堆栈项并不是对象本身,而是一个对象引用。 (TrOr'hy5zGl

7N&t9D*b"{[+F(q{}
#F.JY$^0DVb Java 中的所有对象都要通过对象引用访问。对象引用是指向对象存储所在堆中的某个区域的指针。当声明一个原始类型时,就为类型本身声明了存储。前面的两行代码表示如下:
Vq7Fm2az P9d.c R@/jw7g

D_:{/Q#G j#T1} 引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 riwffHr(Z

y:v2fKIiU
|d?A7q \{ 许多程序的代码将同时包含原始类型以及它们的对象封装。当检查它们是否相等时,同时使用这两种类型并了解它们如何正确相互作用和共存将成为问题。程序员必须了解这两种类型是如何工作和相互作用的,以避免代码出错。 z3U,s9L0B:?-y:b
eR7Z7D0m2IT-o D}

`ptwC\tnU!v'`3Xe 例如,不能对原始类型调用方法,但可以对对象调用方法:
[ruR3X'~oUgc9O A:C8N R s^9yJ

k}Fy&ga/p n3@&S${g%MDFjt
int j = 5;
P.x Rn+@1g
~-z)C.ba ug9g j.hashCode(); // 错误
*nq5{L~9rfb{ry
d5U3q#zp-hAl$g //... (rC)RSU_`

4QL/E&S1~k r;W oa"d Integer i = new Integer(5);
*oOYh8@z\ 4`N-C%jj:e_ A0|
i.hashCode(); // 正确
7MT6Y7A/e,TE
*O9qy7F%c&hIxMO ,\/iNnUy!C3D

1q_F5Wqr
-d }k;s"B%mMoxGj 使用原始类型无须调用 new,也无须创建对象。这节省了时间和空间。混合使用原始类型和对象也可能导致与赋值有关的意外结果。看起来没有错误的代码可能无法完成您希望做的工作。例如:
pD(T7xy&OJ 6Q6jQNBB
2Cn f8}!N-D$w
Fn`*|vM D hS
import java.awt.Point; "W8c{"}XO8}

f*[q UKV E
sw6D"Bj1mnT?yE class Assign
;K,_!}"u n#m]
r!?C\CF { 7s eq8lG
6c_Je!hm
public static void main(String args[])
V2L^2i*V tJ kH0a.w/a1s_v2Sw
{ M+?2Cg;P0a/i\
B#dt `op V
int a = 1; ^Q1Kl%x cZ!gm
}7m2lB8G'\xyE:i Hg ?
int b = 2;
\3Vp&g%j5`V &Lq7s8NK1h4eH9p
Point x = new Point(0,0); _f4SXC'bT,L
P*R(bxgX#e#M5T
Point y = new Point(1,1); //1 @1`8[?S$_%c"S
J}'f5G AU/x
System.out.println("a is " + a);
{_^w`p/K
Q%_zG;MJ;h;f System.out.println("b is " + b); TW4to0? Vau+b6M*@0]

K#qD,q8U[@t System.out.println("x is " + x);
}1])z![+p-Y"M|.|'z9O
V3fG P [R!L System.out.println("y is " + y);
7z)|@)uy%h+JH
|:^&Fn]'cd!S System.out.println("Performing assignment and " +
&T+} tU,r;[ g1x6fn(EjX {0Y0Q,Q
"setLocation...");
9m7Un5z#zy o5hS xI -]&V9VQ fc m
a = b;
T$CaA&NE6V !t;EV)c F)i-BB
a++;
hla$Me.^
S%cZm.?*|1h!w.L x = y; //2
;U7}CBdEF\ q} O \ Btf0ED*}
x.setLocation(5,5); //3
4CT+Y!N?$v}Su/i1L0_
#]"a IE|3^
&tjq|5g@ System.out.println("a is "+a); !t6N G H#d(I1U

zU6~&w#jfM System.out.println("b is "+b); h6jV;RT5Y%O7E+k

(~x9S5p1s+bE H System.out.println("x is "+x); *b(RR9E)ND

4^ eq9E%p&Ir System.out.println("y is "+y);
CxRe B0jb5i*z (gO-xddE
}
:b$c x"}sA!?.K r5xCeKj
}
(dy,m%\$U
2tG\xs D$F V|B-L -[*M4`nm7x3Ey
7{,l;[S.QN
这段代码生成以下输出: "Ze.w(@BT @E
8P ~!XA1hRSH

o`)?"cp/E| X `OjR(^1u"T
a is 1
T}i!{~FV8XJ
%DVBKCe|m?b b is 2 A,C;x8v)C

W|vZL,fp x is java.awt.Point[x=0,y=0] w,F+oRWI ~
iIEmb&j*P1Hq
y is java.awt.Point[x=1,y=1] }A'hr#t4e~ S
:t5K7ks c;n
Performing assignment and setLocation... ~0E ~5se3QQ
d"|q}hqF#D;f
a is 3 RP!S"VN \8`\
|]2xSe,t rt"Jm
b is 2
/B;G$@ sAV0Y)M.O [7nyV8kZ
x is java.awt.Point[x=5,y=5]
/^X$k(N hq)[1`
V$r nw@A3a&i y is java.awt.Point[x=5,y=5] !g|1H0t`Z1C `7i"iP

)ph~&QV!B8W)v*t~p%q 4r Hz.m6{1lo,X

K5Y]2b HXx$u)YW 修改整数 a 和 b 的结果没什么意外的地方。b 的值被赋予整型变量 a,结果 a 的值增加了 1。这一输出反映了我们希望发生的情况。但是,令人感到意外的,是在赋值并调用 setLocation之后 x 和 y 对象的输出。我们在完成 x = y 赋值之后特意对 x 调用了 setLocation,x 和 y 的值怎么会相同呢?我们毕竟将 y 赋予 x,然后更改了 x,这与我们对整数 a 和 b 进行的操作没什么不同。 P&EK2lH
j k/@Z}o5VL

8nK"kdM^(l0O JO 这种混淆是由原始类型和对象的使用造成的。赋值对这两种类型所起的作用没什么不同。但它可能看起来所有不同。赋值使等号 (=) 左边的值等于右边的值。这一点对于原始类型(如前面的 int a 和 b)是显而易见的。对于非原始类型(如 Point 对象),赋值修改的是对象引用,而不是对象本身。因此,在语句 Y@ o djmR

/} L3X%s)X4F ;_L%`9ip%r2{
x = y;
f D/~2m-f+r:D*z
ar!B;~;O2t:z@
*NYR^n%l/DA {
r1j3R|bR@S 之后,x 等于 y。换句话说,因为 x 和 y 是对象引用,它们现在引用同一个对象。因此,对 x 所作的任何更改也会更改 y。下面是 //1 处的代码执行以后的情况:
E^Ha@ DN*?f
wS ]8H6\$U(v?RP
)Xs"xi(Y9Dth5`W*X 执行 //2 处的赋值以后情况如下: PWE"Y,q-B
I.@d-S+P/KM9t1`)Z"y
"[7C!y/]s yYP
当在 //3 处调用 setLocation 时,这一方法是对 x 引用的对象执行的。因为 x 引用的 Point 对象也正是 y 所引用的对象,所以我们现在得到以下结果:
$E1CL#Zh+Jn }(A)y B`3s#sh M
U6zA,W+x*V8hUM
因为 x 和 y 引用同一个对象,所以对 x 执行的所有方法与对 y 执行的方法都作用于同一个对象。 W [-~&V$~ VGf
&_f(Z!C T R(cX

? T6e:?'pT 区分引用类型和原始类型并理解引用的语义是很重要的。若做不到这一点,则会使编写的代码无法完成预定工作。

页: [1]

Powered by 我爱电脑技术论坛 Archiver 6.1.0  © 2001-2007 本SEO插件由网络人站长论坛出品