在Java编程语言中,函数调用时的参数传递方式有两种:传值(Passing by Value)和传引用(Passing by Reference)。虽然Java官方文档中并未明确指出有传引用这一概念,但在实际操作中,Java的行为类似于传引用,尤其是对于对象类型的参数。下面我们将详细探讨这两种传递方式。
对于Java的基本数据类型(如int、char、byte、short、boolean、float、double),函数调用时是按照传值方式进行的。这意味着当一个基本类型的变量作为参数传递到函数时,函数接收的是这个变量的副本,而不是变量本身。例如,在`changeInt(int i)`函数中,`i`是`main`方法中`i`的一个拷贝,函数内部对`i`的修改不会影响`main`方法中的`i`。
```java
public static void changeInt(int i) {
i = 100;
}
```
在上述代码中,`changeInt`函数改变了`i`的副本,但不会影响`main`方法中的`i`。因此,输出`i=0`表明`i`的值未变。
对于引用类型(如类实例),Java的行为看起来像是传引用。当一个对象实例作为参数传递时,函数接收到的是该对象引用的副本,而不是对象本身。这意味着,尽管函数不能改变引用指向的对象,但可以修改对象的属性。例如,`changeModel(Model model)`函数中,`model`是`main`方法中`model`的一个引用副本,函数内部可以修改`model`引用的对象的属性,但不能改变`model`引用本身。
```java
public static void changeModel(Model model) {
model.i = 1;
model.s = "changeModel";
}
```
在这个例子中,`changeModel`函数修改了`model`引用的对象的`i`和`s`属性,但并没有改变`model`引用本身。所以,输出`model:no value`表示`model`对象的`s`属性未变。
然而,如果函数直接修改引用指向的对象,如`changeModel2`函数所示,那么实参引用的成员值会发生改变。
```java
public static void changeModel2(Model model) {
model.i = 1;
model.s = "changeModel";
}
```
在`changeModel2`函数中,`model2`的`s`属性被改变,因此输出`model2:changeModel`。
总结来说,Java中函数参数传递的基本规则是:
1. 对于基本数据类型,参数是值的副本,函数内部对参数的修改不会影响原变量。
2. 对于引用类型,参数是引用的副本,函数可以修改对象的属性,但不能改变引用本身。如果通过引用修改了对象的属性,这些改变会影响到实参引用的对象。
理解这一点对于编写Java程序至关重要,因为它影响到函数如何操作数据以及函数之间的相互作用。在编写涉及对象实例的函数时,开发者必须意识到这种"伪传引用"行为,以避免预期之外的结果。