您的位置:首页 > 编程语言 > Java开发

深入浅出java 函数参数传递原理

2016-05-03 21:29 351 查看
阅读本文之前,先做一道测试题。

import java.util.Arrays;
public class Test {
public static int num=30;
public static String astring="hello";
public static String bstring="world";
public static String cstring="me";
public static String dstring="you";
public static String[] aarray=new String[]{"er","cd","op","af"};
public static void  main(String[] args){
addNum(num);
System.out.println("num="+num);
changeString(astring, bstring);
System.out.printf("astring=%s,bstring=%s\n", astring,bstring);
swapString(cstring, dstring);
System.out.printf("cstring=%s,dstring=%s\n", cstring,dstring);
sortString(aarray);
for (String string : aarray) {
System.out.println(string);
}
}
public static void addNum(int number){
number+=10;
}
public static void changeString(String a,String b){
a=b;
}
public static void swapString(String c,String d){
String temp=c;
c=d;
d=temp;
}
public static void sortString(String [] s){
Arrays.sort(s);
}
}


正确的输出结果是

num=10(没有改变)

astring=hello(没有变成world), bstring=world

cstring=me(没有变成you),dstring=you(没有变成me)

但是字符串数组aarray却变成了{“af”,”cd”,”er”,”op”}

为什么num没有变成20, astring的值没有变成world, cstring和dstring的值没有交换呢?

这是因为java函数传递参数的方式是值传递!!!!

对于8种基本数据类型(byte,short,int,long,float,double,boolean,char)

这些类型的值都存放在栈区,而其它的非基本类型的变量(例如String类实例,或者自定义的类实例等等)保存的都是该对象实例在堆区的地址, 这些值在栈区中存储,而形参得到的就是这些堆区的地址值(值传递体现在这里)

例如int i=10; 存储格式简略图1(图画的我都看不下去了)。



其中AB,AC代表内存地址(为简单起见)

调用addNum函数时,实参num传递给形参number,并把num的值10传递给number, 即number=10, 因为是值的传递,所以另开辟一个内存地址存储该值,这里为AC(原来的内存地址为AB),在函数addNum里面操作的其实是内存AC对应的变量(即number),与原来的变量num没有任何关系,所以num的值没有变为40.

对应与函数changeString,其在内存中存储格式表2



AB,AC,AD,AE代表栈区中的内存地址(存储的内容为对象在堆区的内存地址01,02), 01,02代表堆区中的内存地址(这里地址都做了简化)

形参a复制了astring的值, 形参b复制了bstring的值,

当进行a=b赋值操作的时候,AD里面的值由01变为02,即如图3所示



这时AD,AE都指向02,即bstring ,但是原来的AB,AC中存储的值并没有改变所以astring还是hello

同理对于swapString函数,AD,AE中存储的值进行了互换, 即AD中的值为02,AE中的值为01,但是原来的AB,AC中存储的值并没有改变

所以cstring和dstring的值不会交换。

再来看sortString函数,存储图如图4示。



对于形参s, 新开辟AC内存地址存储堆区的地址值01,

函数内部对s进行排序,这时操作的是堆区中01地址对应的内容,即原来aarray的内容,所以排序会对aarray起作用

可类比调用一个类的实例, 当调用实例的方法修改实例的某一变量时,这个类实例的变量会改变。

public class A {
public static void main(String[] args) {
Test test=new Test("hello");
System.out.println(test.name);
test.setName("world");
System.out.println(test.name);
}

}
class Test{
public String name;
public Test(String name){
this.name=name;
}
public void  setName(String aname){
this.name=aname;
}

}


输出结果依次为hello和

world, 原理同图4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: