今天在编写一个快速排序函数,其中想用一个在C++中类似swap功能的函数,结果引发了一系列的问题。
下面是在网上搜到的代码,并在我的本地机上作了运行。
public class ParamTest
{
public static void main(String[] args)
{
/*
*Test 1:Methods can't modify numeric parameters
*/
System.out.println("Testing tripleValue:");
double percent = 10;
System.out.println("Before: percent =" + percent);
tripleValue(percent);
System.out.println("After: percent = " + percent);
/*
*Test 2: Methods can change the state of object
* parameters
*/
System.out.println("/nTesting tripleSalary:");
Employee harry = new Employee("Harry",50000);
System.out.println("Before: salary =" + harry.getSalary());
tripleSalary(harry);
System.out.println("After: salary =" + harry.getSalary());
/*
*Test 3: Methods can't attach new objects to
* object parameters
*/
System.out.println("/nTesting swap:");
Employee a = new Employee("Alice",70000);
Employee b = new Employee("Bob",60000);
System.out.println("Before: a =" + a.getName());
System.out.println("Before: b =" + b.getName());
swap(a,b);
System.out.println("After: a =" + a.getName());
System.out.println("After: b =" + b.getName());
}
public static void tripleValue(double x) //doesn't work
{
x = 3 * x;
System.out.println("End of method: x=" + x);
}
public static void tripleSalary(Employee x) //works
{
x.raiseSalary(200);
System.out.println("End of method: salary =" + x.getSalary());
}
public static void swap(Employee x, Employee y)
{
Employee temp = x;
x = y;
y = temp;
System.out.println("End of method: x=" + x.getName());
System.out.println("End of method: y=" + y.getName());
}
}
结果:
Testing tripleValue:
Before: percent =10.0
End of method: x=30.0
After: percent = 10.0
Testing tripleSalary:
Before: salary =50000.0
End of method: salary =150000.0
After: salary =150000.0
Testing swap:
Before: a =Alice
Before: b =Bob
End of method: x=Bob
End of method: y=Alice
After: a =Alice
After: b =Bob
这是什么原因呢?分析如下:
对于简单类型,改变参数就是直接对参数赋值。
对于复杂类型,如Integer或封装类型,赋值就是改变了引用,所以当你对它所引用的对象的成员做任何修改都是有效的,
但是如果你像C++中,通过对引用的整个对象操作就是又一次改变了引用。而不是对之前引用的对象做修改。
例如:
void swap(Integer a,Integer b)
{
Integer c=a;
a=b;
b=c;
}
swap(Integer(2),Integer(3));
调用这个函数,形参是对实参的引用,然而,你在函数中又改变了它们的引用位置,并不是赋值,所以实参的值不会改变。
因此如果想写交换函数,最好写成这样:
void swap(int a[],int i,int j)
{
int z=a[i];
a[i]=a[j],a[j]=z;
}