废除Java神话之参数按传址方法通报
副标题#e#
在差异的java新闻组中,参数是传值照旧传址一直是一个常常被争辩的话题。误解的中心是以下两个事实:
工具是传引用的
参数是传值的
这两个可以或许同时创立吗?一个字:是!在java中,你从来没有通报工具,你通报的仅仅是工具的引用!一句话,java是传引用的。然而,当你通报一个参数,那么只有一种参数通报机制:传值!
凡是,当措施员接头传值和传引用时,他们是指语言的参数通报机制,c++同时支持这两种机制,因此,以前利用过c++的措施员开始仿佛不能确定的java是如何传参数的。java语言为了工作变得简朴只支持参数传值的机制。
java中的变量有两种范例:引用范例和原始范例。当他们被作为参数通报给要领时,他们都是传值的。这是一个很是重要的不同,下面的代码典型将说明这一点。在继承前,我们有须要界说一下传值和传引用。
传值意味着当参数被通报给一个要领可能函数时,要领可能函数吸收到的是原始值的副本。因此,假如要领可能函数修改了参数,受影响的只是副本,原始值保持稳定。
关于java中的参数通报的杂乱是因为许多java措施员是从c++转变过来的。c++有引用和非引用范例的变量,而且别离是通过传引用和传值获得的。java语言有原始范例和工具引用,那么,凭据逻辑,java对付原始范例利用传值而对引用范例是传引用的,就像c++一样。究竟,你会想到假如你正在通报一个引用,那么它必然是传引用的。这是一个很诱惑人的想法,可是是错误的!
在c++和java中,当函数的参数不是引用时,你通报的是值得副本(传值)。可是对付引用范例就差异了。在c++中,当参数是引用范例,你通报的是引用可能内存地点(传引用),而在java中,通报一个引用范例的参数的功效只是通报引用的副本(传值)而非引用自身。
这是一个很是重要的区别!java不思量参数的范例,一律通报参数的副本。仍然不信?假如java中是传引用,那么下面的典型中的swap要领将互换他们的参数。因为是传值,因此这个要领不是像期望的那样正常事情。
class Swap
{
public static void main(String args[])
{
Integer a, b;
int i,j;
a = new Integer(10);
b = new Integer(50);
i = 5;
j = 9;
System.out.println(\"Before Swap, a is \" + a);
System.out.println(\"Before Swap, b is \" + b);
swap(a, b);
System.out.println(\"After Swap a is \" + a);
System.out.println(\"After Swap b is \" + b);
System.out.println(\"Before Swap i is \" + i);
System.out.println(\"Before Swap j is \" + j);
swap(i,j);
System.out.println(\"After Swap i is \" + i);
System.out.println(\"After Swap j is \" + j);
}
public static void swap(Integer ia, Integer ib)
{
Integer temp = ia;
ia = ib;
ib = temp;
}
public static void swap(int li, int lj)
{
int temp = li;
li = lj;
lj = temp;
}
}
#p#副标题#e#
上面措施的输出是:
Before Swap, a is 10
Before Swap, b is 50
After Swap a is 10
After Swap b is 50
Before Swap i is 5
Before Swap j is 9
After Swap i is 5
After Swap j is 9
因为swap要领吸收到的是引用参数的副本(传值),对他们的修改不会反射到挪用代码。
译者注:在通报引用和原始范例时照旧有差异的,思量以下的代码:
class Change
{
public static void main(String args[])
{
StringBuffer a=new StringBuffer(\"ok\");
int i;
i = 5;
System.out.println(\"Before change, a is \" + a);
change(a);
System.out.println(\"After change a is \" + a);
System.out.println(\"Before change i is \" + i);
change(i);
System.out.println(\"After change i is \" + i);
}
public static void change(StringBuffer ia)
{
ia.append(\" ok?\");
}
public static void change(int li)
{
li = 10;
}
}
措施的输出为:
Before change, a is ok
After change a is ok ok?
Before change i is 5
After change i is 5
即假如通报的是引用,那么可以修改引用工具的内容,这个改变会影响到本来的工具,而通报的假如是原始范例则不会有影响。这个也是造成误解的原因之一吧。