由JAVA参数传递引发的对引用的思考
2010-04-19 14:29
405 查看
今天在编写一个快速排序函数,其中想用一个在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;
}
下面是在网上搜到的代码,并在我的本地机上作了运行。
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;
}
相关文章推荐
- 由【JAVA中参数传递问题】引发除了基本数据类型和引用类型的思考
- (转)二叉树算法引发的思考:指针参数传递、引用的陷阱
- 二叉树算法引发的思考:指针参数传递、引用的陷阱
- 二叉树算法引发的指针参数传递和引用的思考
- 二叉树算法引发的思考:指针参数传递、引用的陷阱
- java中基本类型的参数传递和引用类型的参数传递
- Java参数传递到底是值传递还是引用传递?
- Java 方法参数的值传递和引用传递
- java程序设计--孙鑫java无难事Lesson5《java常用包、数据类型与引用类型、函数参数传递、克隆机制》
- 面试之路(18)-java的函数参数传递类型之值传递还是引用传递
- java参数传递究竟是按值呢,还是引用?
- Java中函数参数的传递形式是值传递 还是引用传递
- JAVA中函数调用参数传递的理解(值传递和引用传递的理解)
- Java传递基本类型:值传递,对象作为参数:引用传递
- 临时变量作为非const的引用进行参数传递引发的编译错误
- JAVA方法传递参数:传值?传引用?
- Java中函数参数的传递是值传递还是引用传递
- java中的参数传递——值传递、引用传递
- java引用与参数传递
- Java函数参数的值传递和引用传递