Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)

时间:2022-04-27 21:25:30

原文地址:http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

在Java中,所有的对象变量都是引用,Java通过引用来管理对象。然而在给方法传参时,Java并没有使用传引用的方式,而是采用了传值的方式。例如下面的badSwap()方法:

public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}
当badSwap方法时,原有的var1和var2的值并不会发生变化。即使我们用其它Object类型来替代int,也不会有变化,因为Java在传递引用时也是采用传值的方式。(译者注:这里是关键,全文的核心是:1. Java中对象变量是引用 2. Java中方法是传值的 3. 传方法中参数时,传递的是引用的值)

如果译者的注释没看明白,没关系,看看下面的代码:

public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}
执行main()的输出如下:

X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0
这个方法成功地改变了pnt1的值,但pnt1和pnt2的交换却失败了!这是Java参数传递机制里最让人迷惑的地方。在main()中,pnt1和pnt2是Point对象的引用,当将pnt1和pnt2传递给tricky()时,Java使用的正是传值的方式,将这两个引用的传给了arg1和arg2。也就是说arg1和arg2正是pnt1和pnt2的复制,他们所指向的对象是相同的。详情可见下面的图示:

Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)

图 1. 在作为参数传递后,对象至少有两个引用指向自己

Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail. As Figure 2 illustrates, the method references swap, but not the original references. Unfortunately, after a method call, you are left with only the unswapped original references. For a swap to succeed outside of the method call, we need to swap the original references, not the copies.

在main()中,引用被复制并以传值的方式进行传递,对象本身并不会被传递。因此,tricky()方法中pnt1所指向的对象发生了变化。因为传递的是引用的复制,因此引用的交换既不能引起对象的交换,更不会使原始引用发生变化。如图2所示,tricky()交换了arg1与arg2,但不会影响pnt1和pnt2。因此若想交换原始引用pnt1和pnt2,那么不能通过调用方法的方式来实现。

Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)

图 2. 只有作为参数的引用发生了交换,但原始引用并没有变化

总结:

1. Java中对象变量是引用 

2. Java中方法是传值的 

3. 传方法中参数时,传递的是引用的值


原文如下:

Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.

Take the badSwap() method for example:


public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}


When badSwap() returns, the variables passed as arguments will still hold their original values. The method will also fail if we change the arguments type fromint toObject, since Java passes object references by value as well. Now, here is where it gets tricky:


public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}

If we execute this main() method, we see the following output:

X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0



The method successfully alters the value of pnt1, even though it is passed by value; however, a swap ofpnt1 andpnt2 fails! This is the major source of confusion. In themain() method,pnt1 andpnt2 are nothing more than object references. When you passpnt1 andpnt2 to thetricky() method, Java passes the references by value just like any other parameter. This means the references passed to the method are actuallycopies of the original references. Figure 1 below shows two references pointing to the same object after Java passes an object to a method.

Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)

Figure 1. After being passed to a method, an object will have at least two references



Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail. As Figure 2 illustrates, the method references swap, but not the original references. Unfortunately, after a method call, you are left with only the unswapped original references. For a swap to succeed outside of the method call, we need to swap the original references, not the copies.

Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass by value?)

Figure 2. Only the method references are swapped, not the original ones

About the author

Tony Sintes is a principal consultant at BroadVision. Tony, a Sun-certified Java 1.1 programmer and Java 2 developer, has worked with Java since 1997.O'Reilly's Java in a Nutshell by David Flanagan (see Resources) puts it best: "Java manipulates objects 'by reference,' but it passes object references to methods 'by value.'" As a result, you cannot write a standard swap method to swap objects.