手记

Java 方法中参数的传递方式

在《Java核心技术 卷一 基础知识》第4.5节中专门讲解了方法参数,里面有一句话:Java程序设计语言总是采用按值调用。整个一节都是围绕着一句话来进行讲解,内容比较抽象,后来在stackoverflow上面看到了相关内容的精彩讨论(Is Java “pass-by-reference” or “pass-by-value”?),在此做近一步整理。

首先先明确几个术语,基本数据类型和引用类型(对象引用)是方法中参数的两种类型,按值调用和按引用调用是方法中参数的两种传递方式。注意这里的几个术语是一般程序设计语言中的术语,并非特指Java。

毋庸置疑的是,在Java中,方法的参数类型有基本数据类型和对象引用。例如,foo(int a)的参数类型是基本数据类型,foo(String a)的参数类型是引用类型。下面分别对这两类情况进行说明。

  1. 基本数据类型作参数

针对于参数类型是基本数据类型的情况,代码如下:

public class Test {

public static void tripleValue(double x){
  x = 3*x;
  System.out.println("在方法tripleValue() 内部, x = " + x);//x=6.0
}

public static void main(String[] args){
  double a = 2;
  System.out.println("调用方法 tripleValue() 之前, a = " + a);// a = 2.0
  tripleValue(a);
  System.out.println("调用方法 tripleValue() 之后, a = " + a);// a = 2.0
}
}

输出

调用方法 tripleValue() 之前, a = 2.0
在方法tripleValue() 内部, x = 6.0
调用方法 tripleValue() 之后, a = 2.0

上面这个比较简单,输出结果在预料之中,借用这个简单的例子,通过绘制图形的方式,来表示Java虚拟机是样分配内存的。

首先 double a = 2; 声明类一个基本数据类型a并为它赋予了初值2, Java虚拟机在栈顶分配了一块8字节的内存存储数值2.0。

前面声明的double类型的变量a属于基本数据类型,tripleValue方法以按值调用的方式调用a,此时传入tripleValue方法中的是a的一个拷贝。

当tripleValue方法内部执行 x = 3*x; 语句时实际上仅仅对a的拷贝进行了乘3操作,而a本身的值没有发生改变。

  1. 对象引用作参数

先亮代码:

public class HelloWorld
{
  public static void reName(String name){
    name += "re";
  }

  public static void main(String[] args){
    String oldName = "Bob";
    System.out.println(oldName);
    reName(oldName);
    System.out.println(oldName);

  }
}

输出:

Bob
Bob

与基础数据类型double不同,String属于引用类型,即变量存的是对象的地址。同样,上面代码main方法中声明oldName之后,Java虚拟机内存分配的情况可用下图表示。

方法reName调用oldName时,我们先不管它是按照什么方式调用,先看reName方法质执行的过程。当reName方法内部执行语句 name += "re"; 时,JVM将创建一个新的String对象"reBob",即相当于执行了语句name = new String("reName"), name指向"reName"。

此时,若reName是按引用调用"Bod"对象的引用oldName, 则oldName和name都将指向新的对象"reBod";若reName按值调用"Bod"对象的引用oldName, 则name和oldName将指向不同的对象。从执行结果中我们可以看到,执行reName之后再打印oldName,结果仍然是"Bob",这表明oldName指向的对象仍然为"Bob"。

故在Java中,对象引用作参数时,方法按值调用实参,即方法得到的是对象引用的一个拷贝。

所以说:“Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,特别是方法不能修改传递给它的任何参数变量的内容”。

0人推荐
随时随地看视频
慕课网APP

热门评论

这是对Java的理解不到位呀,对引用类型的理解太片面了

查看全部评论