Practical Java
Programming Language Guide
Practical Java
中文版
[ 美 ] Peter Haggar 著
侯捷 刘永丹 译
出自第一线 Java 编程专家之手
68 个改善代码的重要主题
所有示例和方案均有详尽解说
中国电力出版社
w ww.infopower.com.cn
Java
Java
Java
Java
开 发 大 师 系 列
Addison
Wesley
目录
Contents
实践:实际履行,尤指艺术、科学或技术领域;与理论遥相对应。
1
1
1
1 一般技术
实践 1
1
1
1 :参数以 by
by
by
by value
value
value
value 方式而非 by
by
by
by reference
reference
reference
reference 方式传递
一个普遍存在的误解是: java 中的参数以 by reference 方式传递。这不是 真
的, 参数其实是以 by value 方式传递。 这个误解源于 [ 所有 java object s 都 是
objects references] 事实(关于 object references 的详细信息,请见实践 8
) 。
如果你未能准确理解其中奥妙,则可能导致一些料想不到的后果。举个例
子:
这段代码在 //2 外建立了一个 point 对象并设初值为( 0 , 0
) ,接着将其值
赋
予 object reference 变量 p 。 然后对基本型别 int i 赋予数值 10
。
//3 调用 stati c
modifyPoint()
, 传入
p 和 i
。
modifyPoint () 对第一个参数 pt 调用了 setLo cation
() , 将其坐标改为 (5, 5) 。 然后将第二个参数
j 赋值为15。 当 modi fyPoint
() 返回的时候,
main() 打印出 p 和 i 的值。 这段代码的输出为何?为什 么?
程序输出如下:
这显示, modifyPoint ()改变了 //2 所建立的 Point 对象,却没有改变 int i
。
在 main ()之中, i 被赋值为 10 。由于参数通过 by value 方式传递,所以
modifyPoint () 收到 i 的一个副本, 然后它将这个副本改为 15
并返回。
m ain()
内的原值 i 并没有受到影响。
对比这下,你或许认为 //2 建立的 point 对象也没有被 modifyPoint()
修改。
毕竟 java 是通过 by value 方式传递参数。于是乎,当调用 modifyPoint
()
并传入 //2 所建立的 point
对象时, 就会产生一个复件 (
copy
) 配合
modify Point
()工作。 modifyPoint ()之中对于 point 对象所做的修改不会反映到 ma in
()中,因为它们是两个不同的对象嘛。对不对?错!
事实上 modifyPoint ()是与在 [point 对象的 reference 的复件 ] 打交道,而 不
是与 [Point 对象的复件 ] 打交道。记住, p 是个 object reference ,并且 Java
以 by value 方式传递参数。更明确地说, Java 以 by value 方式传递 object
reference 。当 p 从 main ()被传入 modifyPoint ()时,传递的是 p (也就
是一个 reference )的复件。所以 modifyPoint () 是在与同一个对象打交道
,
只不过通过别名 pt 罢了。在进入 modifyPoint ()之后和执行 //1 之前,这
java中的索引看做是指针,参数是值拷贝。
个对象看起来是这样:
Point
Point
Point
Point
p
p
p
p
pt
pt
pt
pt
所以 //1 执行过后,这个 point 对象已经改变为( 5 , 5
) 。如果你不同意在
诸
如 modifyPoint ()这样的函数内改变 Point 对象,该怎么办?有两种解决
办法:
� 对 modifyPoint ()传递一个 point 对象的克隆件( clone ) 。关于克隆
( cloning )的具体信息,请见实践 64 和实践 66 。
� 令 point 对象成为 immutable (不可变的) 。实践 65 对于 immutable 对 象
技术有所讨论。
实践 2
2
2
2 :对不变的 date
date
date
date 和 object
object
object
object references
references
references
references 使用 final
final
final
final
许多语言都提供常量数据( constant data )的概念,用来表示那些既不会 改
变也不能被改变的数据。 J ava 关键词 final 用来表示常量数据。例如:
这段代码声明了一个 static 类变量,命名为 someInt 并设其初值为 10 。
任何试图修改 someInt 的代码都将无法通过编译。例如:
X
X
X
X =
=
=
= 0
0
0
0
y
y
y
y =
=
=
= 0
0
0
0