站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题Java “Pass by value” 解析

Java “Pass by value” 解析

摘要: Java “Pass by value” 解析

我在许多论坛和文章的答复上看到很多人都认为Java是pass by reference的,但我
查了些资料,确实Java是pass by value的。如果你已了解java是pass by vlaue而
非pass by reference的,那么你就可以pass这篇文章了,看其他你喜欢的文章去吧
!如果你不以为Java是pass by vlaue或还坚信Java是pass by reference的,那么
就跟着我的思路走一下吧。我会让你了解Java到底是pass by value还是pass by
referenve。本人是个菜鸟,只是把自己所学的东西写出来给同级别的菜鸟学习学习
。望高手看了多多指教,不要见笑。
Java是使用“pass by value”『函数调用』方式,这常常造成许多人迷惑。在所有
地点,Java都严格采用pass by value。让我们来看一个简单的例子:
清单一:
class Param {
public static void main (String[] args) {
int x = 5;
triple(x);
System.out.println ("x after triple: " + x); }
private static void triple (int arg) {
arg = arg * 3;
System.out.println ("arg in triple: " + arg); } }
会产生这样的输出:
arg in triple: 15
x after triple: 5
这段代码只是传入一个int而已,还不至于让人糊涂。但如果参数中传递的是一个对
象,就可能把你弄迷糊了。如果我在程序中以Date对象表示日期,那么程序看起来想这样:
清单二:
import java.util.*;
class Param {
public static void main (String[] args) {
Date d1 = new Date ("1 Jan 2004");
nextDateUpdate (d1);
System.out.println ("d1 after nextDay: " + d1);
Date d2 = new Date ("1 Jan 2004");
nextDateReplace (d2);
System.out.println ("d2 agter nextDay: " + d2); }
private static void nextDateUpdate (Date arg) {
arg.setDate (arg.getDate() + 1);
System.out.println ("arg in nextDay: " + arg); }
private static void nextDateReplace (Date arg) {
arg = new Date (arg.getYear(),arg.getMonth(),arg.getDate() + 1);
System.out.println ("arg int nextDay: " + arg); } }
会产生这样的输出:
arg in nextDay: Jan 02 00:00:00 CST 2004
d1 after nextDay: Jan 02 00:00:00 CST 2004
arg int nextDay: Jan 02 00:00:00 CST 2004
d2 agter nextDay: Jan 01 00:00:00 CST 2004
这个实例可能让你看起来有点迷惑。有人会说如果java是pass by value的话,d1
after nextDay:应该为Jan 01 00:00:00 CST 2004才对!错!Java中的对象是
object reference。事实上,nextDateReplace()是在与『Date对象(d2)的
reference的复件』打交道,而不是与『Date对象(d2)的复件』打交道。在进入
nextDateUpdate(Date arg)之时,这个对象看起来象这样:
聪明的你这下应该明白了吧!如果还没明白!没关系,再来一个更详细的例子:
清单三:
import java.awt.Point;
class Param {
public static void main (String[] args) {
Point p = new Point(0,0); //1
int i = 10;
System.out.println ("Before modifyPoint: " + "p = " + p +
" and i = " + i);
modifyPoint (p,i); //2
System.out.println ("After modifyPoint: " + "p = " + p +
" and i = " + i); }
private static void modifyPoint (Point pt , int j) {
pt.setLocation (5,5); //3
j = 15;
System.out.println ("During modifyPoint: " + "pt = " + pt +
" and j = " + j); } }
会产生这样的输出:
Before modifyPoint: p = java.awt.Point[x=0,y=0] and i = 10
During modifyPoint: pt = java.awt.Point[x=5,y=5] and j = 15
After modifyPoint: p = java.awt.Point[x=5,y=5] and i = 10
这段代码在//1处建立了一个Point对象并设初值为(0,0),接着将其值赋予Object
reference变量p。然后对基本型别int I赋予数值10。//2调用static
modifyPoint(),传入p和i。modifyPoint()对第一个参数pt调用了setLocation(),
将其坐标改为(5,5)。然后将第二个参数j赋值为15。当modifyPoint()返回的时
候,main()打印出p和i的值。
根据程序输出,modifyPoint()改变了//1所建立的Point对象,却没有改变int i。
在main()之中,i被赋值为10。由于参数通过by value方式传递,所以modifyPoint
()收到i的一个副本,然后它将这个副本改为15并返回。main()内的原值i并没有受到影响。
对比之下,你或许认为//1建立的point对象也没有被modifyPoint()修改。毕竟Java
是pass by value方式来传递参数。于是乎,当调用modifyPoint()并传入//1所建立
的point对象时,就会产生一个复件配合modifyPoint()工作。modifyPoint()之中对
于point对象所做的修改不会反映到main()中,因为它们是两个不同的对象嘛。对不对?错!
事实上modifyPoint()是在与是在与『point对象的reference的复件』打交道,而不
是与『point对象的复件』打交道。你知道的,p是个object reference,并且Java
是pass by vlaue方式传递参数。更明确的说,Java是以by value方式传递object
reference。当p从main()被传入modifyPoint()时传递的是p(也就是一个reference
)的复件。所以modifyPoint()是在与同一个对象打交道,只不过通过别名pt罢了。
在进入modifyPoint()之后和执行//3之前,这个对象看起来象这样:
所以//3执行过后,这个point对象已经改变为(5,5)。
结语:通过上面说的,Java是pass by value方式传递参数的。当然就算你已知
道java是pass by value方式传递参数的,它有时也会让你感到迷糊。从本质上说,
object reference是按值传递的(pass by value),因此我们能够修改参数对象的内
部状态。我们应该采用《重构》中的‘Remove Assignments to Parameters’进行
重构,以此来避免可能发生的问题。
↑返回目录
前一篇: Java API To Access Microsoft Excel Format
后一篇: Java 3D图形API