深入浅出java 函数参数传递原理
2016-05-03 21:29
351 查看
阅读本文之前,先做一道测试题。
正确的输出结果是
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起作用
可类比调用一个类的实例, 当调用实例的方法修改实例的某一变量时,这个类实例的变量会改变。
输出结果依次为hello和
world, 原理同图4
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
相关文章推荐
- spring事物传播特性
- 奇数-函数实现
- 使用JUnit测试java代码
- qpid java broker的安装和配置
- Java实现:统计英语词库中某单词是另一单词后缀的次数问题
- Kafka消息生产消费的一个java小案例(伪分布)
- Java八种基本数据类型所占字节
- 《java入门第一季》之参数引用
- 《java入门第一季》之参数引用
- Spring+Swagger文档无法排序问题解决
- Java多线程-新特征-信号量Semaphore
- Java:Comparator接口
- java--HibernateSynchronizer在MyEclipse中的配置
- 在eclipse操作hbase时,遇到的问题
- JAVA 的几种单例模式以及优缺点
- 数组相加
- 20160503-spring入门1
- Java核心技术(三) —— 对象与类(2)
- java常用集合及相关接口
- java关键字final