1. 方法参数的传递方式

“按…………调用”(call by)是一个标准的计算机科学术语,用来描述各种程序设计语言中方法参数的传递方式。

方法参数的传递方式:

  • 按值调用(call by value)表示方法接收的是调用者提供的值。
  • 按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。

方法可以修改按引用传递的变量的值,而不能修改按值传递的变量的值。

Java 程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个副本。具体讲,方法不能修改传递给它的任何参数变量的内容。

public class ParamTest {
    public static void tripleValue(double x) {
        x = 3 * x;
        System.out.println("方法结束时,x = " + x);
    }
    public static void main(String[] args) {
        double x = 10;
        System.out.println("调用方法前,x = " + x);
        ParamTest.tripleValue(x);
        System.out.println("调用方法后,x = " + x);
    }
}

打印结果:

调用方法前,x = 10.0
方法结束时,x = 30.0
调用方法后,x = 10.0

一个方法不可能修改一个基本数据类型的参数。
实现一个改变对象参数状态的方法完全是可以的,也相当常见。理由很简单,方法得到的是对象引用的副本,原来的对象引用和这个副本都是同一个对象。

有些程序员认为 Java 程序设计语言对对象采用的是按引用调用,实际上,这种理解是不对的。下面是一个反例。

import java.util.Objects;

public class ParamTest {
    public static void swap(Employee x, Employee y) {
        Employee temp = x;
        x = y;
        y = temp;
    }
    public static void main(String[] args) {
        Employee a = new Employee("A", 10000);
        Employee b = new Employee("B", 5000);
        System.out.println(a);
        System.out.println(b);

        // A 的工资增加 200%
        a.raiseSalary(200);
        // 交换 a 和 b 的对象
        ParamTest.swap(a, b);
        System.out.println("调用 Employee 对象交换方法后");
        System.out.println(a);
        System.out.println(b);
    }
}
class Employee {
    private String name;
    private double salary;
    public Employee(String name, double salary) {
        Objects.requireNonNull(name, "The name cannot be null");
        this.name = name;
        this.salary = salary;
    }
    /**
     * 增加工资
     * @param byPercent 百分比
     */
    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }

    public String toString() {
        String str = "%s[name=%s,salary=%s]";
        return String.format(str, getClass(), name, salary);
    }
}

打印结果:

class Employee[name=A,salary=10000.0]
class Employee[name=B,salary=5000.0]
调用 Employee 对象交换方法后
class Employee[name=A,salary=30000.0]
class Employee[name=B,salary=5000.0]

从执行的结果中可以看到,变量 a 和变量 b 的对象没有交换,这说明:Java 程序设计语言对对象采用的不是按引用调用。变量 a 的对象状态发生了改变,说明,Java 程序设计语言对象方法参数可以改变对象的状态。
Java 程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。

下面总结一下在 Java 中方法参数能做什么和不能做什么:

  • 方法不能修改基本数据类型的参数(即数值型或布尔型)
  • 方法可以改变对象参数的状态。
  • 方法不能让一个对象参数引用一个新的对象。