查看“为什么说Java中只有值传递?”的源代码
←
为什么说Java中只有值传递?
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Java]] == 关于 == 调用一个有参函数的时候,会把实际参数传递给形式参数。 但是,在程序语言中,这个传递过程中传递的两种情况,即值传递和引用传递。 === 形参 与 实参 === # '''形式参数''':是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。【参数的占位符】 # '''实际参数''':在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。【参数的真实内容】 示例: : <syntaxhighlight lang="Java" highlight=""> public class NormalTest { public void print(String str){ // 形参为 str System.out.println(str); } public static void main(String[] args) { NormalTest nt = new NormalTest(); nt.print("Eijux"); // 实参为 "Eijux" } } </syntaxhighlight> === 值传递 与 引用传递 === # '''值传递'''(pass by value):在调用函数时将'''复制的实参值'''传递到函数中; #* 函数中对参数进行的修改,'''不会影响实参'''。 # '''引用传递'''(pass by reference):在调用函数时将'''实参地址'''直接传递到函数中; #* 函数中对参数进行的修改,'''将影响到实参'''。 示例: : <syntaxhighlight lang="Java" highlight=""> public class NormalTest { public void print(int j) { j = 20; System.out.println("print in pass , j is " + j); } public static void main(String[] args) { NormalTest nt = new NormalTest(); int i = 10; nt.print(i); System.out.println("print in main , i is " + i); } } </syntaxhighlight> : <syntaxhighlight lang="Java" highlight=""> print in pass , j is 20 print in main , i is 10 </syntaxhighlight> == “值传递”的理解 == 关于“值传递”,有几个常见的错误理解: # (参数类型)如果传递的是“普通类型”,那就是“值传递”;如果传递的是“对象类型”,那就是“引用传递”。 # (参数内容)“值传递”和“引用传递”的区别是“传递的内容”:如果是个值,就是值传递;如果是个引用,就是引用传递。 === 辨析 === # 示例一:(错误理解) #: <syntaxhighlight lang="Java" highlight="3"> public class NormalTest { public void print(User user) { user.setName("Xuelinzi"); System.out.println("print in pass , user is " + user); } public static void main(String[] args) { NormalTest nt = new NormalTest(); User usr = new User(); usr.setName("Eijux"); usr.setGender("Male"); nt.print(usr); // 传递实参 usr System.out.println("print in main , user is " + usr); } static class User{ private String name; private String gender; public void setName(String name){ this.name = name; } public void setGender(String gender){ this.gender = gender; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", gender='" + gender + '\'' + '}'; } } } </syntaxhighlight> #: <syntaxhighlight lang="Java" highlight=""> print in pass , user is User{name='Xuelinzi', gender='Male'} print in main , user is User{name='Xuelinzi', gender='Male'} </syntaxhighlight> #: 如上所示:看似是在 print 方法中,将实参 usr 改变了,好像是“如果传递的是对象类型,那就是引用传递”,或“传递的内容是个引用,就是引用传递”。 # 示例二:(辨析理解) #: <syntaxhighlight lang="Java" highlight="3-4"> public class NormalTest { public void pass(User user) { user = new User(); user.setName("Xuelinzi"); user.setGender("Male"); System.out.println("print in pass , user is " + user); } public static void main(String[] args) { NormalTest nt = new NormalTest(); User usr = new User(); usr.setName("Eijux"); usr.setGender("Male"); nt.pass(usr); // 传递实参 usr System.out.println("print in main , user is " + usr); } static class User{ private String name; private String gender; public void setName(String name){ this.name = name; } public void setGender(String gender){ this.gender = gender; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", gender='" + gender + '\'' + '}'; } } } </syntaxhighlight> #: <syntaxhighlight lang="Java" highlight=""> print in pass , user is User{name='Xuelinzi', gender='Male'} print in main , user is User{name='Eijux', gender='Male'} </syntaxhighlight> 两个示例的执行过程: # 在 main 中: ## 创建 User 对象时,会在堆中开辟一块内存(0x11111111),并交由 usr 指向到该内存地址; ## 调用 pass 方法时,会将“实参”(usr)传递给“形参”(user),此时“usr”、“user”都将会指向内存(0x11111111)。 # 在 pass 中: ## 若直接调用“user.setName()”等方法,则将会修改内存(0x11111111)中的内容; ## 若首先调用“user = new User();”方法,则将在堆中重新开辟一块内存(0x22222222),并将“形参”(user)指向该新内存地址; ##: 此时再调用“user.setName()”等方法,则将会修改内存(0x22222222)中的内容; : 所以:传递“对象类型”时,是把“实参”对象所引用的“'''内存地址'''”当做值传递给了“形参”。 而输出内容的差别,则是因为: # 示例一,输出不同:通过“形参”(由于值传递,指向与“实参”相同的内存),修改了'''内存地址中所存储的数据'''。 #* 修改的是内存中的数据,并没有修改“形参”,更没有影响到“实参”; # 示例二,输出相同:修改“形参”(由于 new,指向了与“实参”不同的内存),输出内容也分别是两个内存块的数据(独立,但属性相同)。 #* 修改的是“形参”,而并没有影响到“实参”; 由此可以看出: <big>'''无论是传递“普通类型”还是“对象类型”,所使用的都是“值传递”'''。</big> 同时可以看出: <big>'''值传递和引用传递的区别,是实参到底有没有被复制一份给形参''',而不是并不是传递的内容(如上:传递引用,仍然是“值传递”)</big> == 按共享传递 == 无论是值传递还是引用传递,其实都是一种'''求值策略'''(Evaluation strategy),在求值策略中,还有一种叫做按“'''共享传递'''”(call by sharing)。 其实 Java 中的参数传递严格意义上说应该是:'''按共享传递'''。 按共享传递——是指在调用函数时,传递给函数的是“实参的地址的拷贝”(如果实参在栈中,则直接拷贝该值)。 在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作: 1、如果原值在栈中(实参值即为栈中值),那么直接拷贝该值。 ——'''因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响'''。 2、如果原值在堆中(实参值为堆中的地址),则需先根据该地址找到堆中对应的位置,再进行操作。 ——'''因为传递的是地址的拷贝,所以函数内对值的操作对外部变量是可见的'''。(如上一节的示例) 总之: * Java 中的传递,是值传递,而这个值,实际上是对象的引用。 *“按共享传递”可以看作“按值传递”的一个特例。
返回至“
为什么说Java中只有值传递?
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息