java,call-by-value还是call-by-reference?

    我们都知道,在java语言中,对于几种基本数据类型,都是call-by-value,如以下例子:

public static void tripleValue(double x) // doesn't work
{
   x = 3 * x;

}

public static void main(Strings[] args)

{

    double percent = 10;
    tripleValue(percent);

}

    这个例子中,并没有实现将percent乘三,因为基本数据类型是call-by-value。

    但是对于引用类型呢?是call-by-value还是call-by-reference呢?先看一个例子:

class Employee
{
    ...
    private double salary;
    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
}

class test
{
    public static void main(String[] args)
    {
        harry = new Employee();
        tripleSalary(harry);
    }
    public static void tripleSalary(Employee x) // works
    {
        x.raiseSalary(200);
    }
}

    这个例子中,能够成功地把harry的薪水上涨两倍,为什么呢?看一下过程:

    首先,tripleSalary(harry)先复制harry给x。harry是什么?是一个Employee引用,所以得到x也是一个Employee也是一个引用,且这两个引用指向同一个对象,然后tripleSalary方法中,x再调用raiseSalary方法,因为x是一个对象的引用,所以此时确实改变了所指对象的salary域,所以方法调用结束后,harry的salary发生了改变。整个过程通过下图一目了然:

java,call-by-value还是call-by-reference?

   那么,对于引用对象,方法参数传递的是地址吗?

   其实不是,再通过最后一个例子就可以看清楚了:

class test
{
    public static void swap(Employee x, Employee y) // doesn't work
    {
        Employee temp = x;
        x = y;
        y = temp;
    }
    public static void main(String[] args)
    {
        Employee a = new Employee("Alice", . . .);
        Employee b = new Employee("Bob", . . .);
        swap(a, b);
// does a now refer to Bob, b to Alice?
    }
}

   这个例子最后并没有真正交换a和b所引用的对象,为什么呢?看下图就可以知道:

java,call-by-value还是call-by-reference?

   可以看出,在调用swap(a, b);时,a、b各复制一个副本给x、y,然后交换x、y所引用的对象,最后退出函数调用时,x、y销毁,但是a、b所引用的还是原来的对象,并没有实现交换的目的,因此,对于引用对象类型,方法参数传递仍是call-by-value,只是第二个例子中,复制的是对象的引用,并且在方法内使用这个引用改变了对象的状态,最后让我们看到的好像是call-by-reference的假象,但其实还是call-by-value,只是这时的value是一个reference,第三个例子也一样,只不过第三个例子中没有通过这个引用在方法内修改这个对象而已,所以方法调用结束后,复制的value自动销毁。