Java里只有“值传递”,没有“引用传递”。
# 谷强强 写道
值传递和引用传递,属于函数调用时参数的求值策略(Evaluation Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。
值类型/引用类型,是用于区分两种内存分配方式,值类型在调用栈上分配,引用类型在堆上分配。(不要问我引用类型里定义个值类型成员或反之会发生什么,这不在这个本文的讨论范畴内,而且你看完之后,你应该可以自己想明白)。
值类型/引用类型描述内存分配方式,值传递/引用传递描述参数求值策略,两者之间无任何依赖或约束关系。
写道值类型/引用类型,是用于区分两种内存分配方式,值类型在调用栈上分配,引用类型在堆上分配。(不要问我引用类型里定义个值类型成员或反之会发生什么,这不在这个本文的讨论范畴内,而且你看完之后,你应该可以自己想明白)。
值类型/引用类型描述内存分配方式,值传递/引用传递描述参数求值策略,两者之间无任何依赖或约束关系。
在函数调用过程中,调用方提供实参,
这些实参可以是常量: Call(1);
也可以是变量: Call(x);
也可以是他们的组合: Call(2 * x + 1);
也可以是对其它函数的调用:Call(GetNumber());
但是所有这些实参的形式,都统称为表达式(Expression)。
求值(Evaluation)即是指对这些表达式的简化并求解其值的过程。
求值策略(值传递和引用传递)的关注的点在于,这些表达式在调用函数的过程中,求值的时机、值的形式的选取等问题。求值的时机,可以是在函数调用前,也可以是在函数调用后,由被调用者自己求值。这里所谓调用后求值,可以理解为Lazy Load或On Demand的一种求值方式。
这些实参可以是常量: Call(1);
也可以是变量: Call(x);
也可以是他们的组合: Call(2 * x + 1);
也可以是对其它函数的调用:Call(GetNumber());
但是所有这些实参的形式,都统称为表达式(Expression)。
求值(Evaluation)即是指对这些表达式的简化并求解其值的过程。
求值策略(值传递和引用传递)的关注的点在于,这些表达式在调用函数的过程中,求值的时机、值的形式的选取等问题。求值的时机,可以是在函数调用前,也可以是在函数调用后,由被调用者自己求值。这里所谓调用后求值,可以理解为Lazy Load或On Demand的一种求值方式。
求值策略 | 求值时机 | 传值方式 |
值传递(pass by value) | 调用前 | 值的副本(原始对象的副本) |
引用传递(pass by reference) | 调用前 | 原值(原始对象) |
名传递(pass by name) | 调用后 | 与值无关的一个名 |
则 值传递与引用传递 的区别:
值传递 | 引用传递 | |
根本区别 | 创建副本(copy) | 不创建副本 |
所以 | 在函数中无法改变对象 | 在函数中可以改变对象 |
写道
这里的改变不是指mutate, 而是change,指把一个变量指向另一个对象,而不是指仅仅改变属性或是成员什么的.
所以说Java是Pass by value,原因是它调用时Copy,实参不能指向另一个对象,而不是因为被传递的东西本质上是个Value.
写道
这些行为,与参数类型是值类型还是引用类型无关。
对于值传递,无论是值类型还是引用类型,都会在调用栈上创建一个副本,不同是,对于值类型而言,这个副本就是整个原始值的复制。而对于引用类型而言,由于引用类型的实例在堆中,在栈上只有它的一个引用(一般情况下是指针),其副本也只是这个引用的复制,而不是整个原始对象的复制.
这便引出了值类型和引用类型(这不是在说值传递)的最大区别:值类型用做参数会被复制,但是很多人误以为这个区别是值类型的特性。其实这是值传递带来的效果,和值类型本身没有关系。只是最终结果是这样。
综上所述,对于Java的函数调用方式最准确的描述是:参数藉由值传递方式,传递的值是个引用。
由于这个描述太绕,而且在字面上与Java总是传引用的事实冲突。于是对于Java,Python、Ruby、JavaScript等语言使用的这种求值策略,起了一个更贴切名字,叫Call by sharing。这个名字诞生于40年前。
对于值传递,无论是值类型还是引用类型,都会在调用栈上创建一个副本,不同是,对于值类型而言,这个副本就是整个原始值的复制。而对于引用类型而言,由于引用类型的实例在堆中,在栈上只有它的一个引用(一般情况下是指针),其副本也只是这个引用的复制,而不是整个原始对象的复制.
这便引出了值类型和引用类型(这不是在说值传递)的最大区别:值类型用做参数会被复制,但是很多人误以为这个区别是值类型的特性。其实这是值传递带来的效果,和值类型本身没有关系。只是最终结果是这样。
综上所述,对于Java的函数调用方式最准确的描述是:参数藉由值传递方式,传递的值是个引用。
由于这个描述太绕,而且在字面上与Java总是传引用的事实冲突。于是对于Java,Python、Ruby、JavaScript等语言使用的这种求值策略,起了一个更贴切名字,叫Call by sharing。这个名字诞生于40年前。
call-by-reference: You are able to assign a new reference to a method parameter variable in a method, and it will be visible by the caller of the method so after calling the method, the caller will get the new reference (new object).
call-by-sharing: You are able to assign a new reference to a method parameter variable in a method, BUT it will NOT be visible by the caller of the method so after calling the method, the caller will still get the same old reference which was passed as a method parameter to the method.
call-by-sharing: You are able to assign a new reference to a method parameter variable in a method, BUT it will NOT be visible by the caller of the method so after calling the method, the caller will still get the same old reference which was passed as a method parameter to the method.
Java代码
public class ReferenceTest { public static void main(String[] args) { StringBuffer str = new StringBuffer("aaa"); change1(str); System.out.println(str); // aaa change11(str); System.out.println(str); // aaabbb change12(str); System.out.println(str); // aaabbbbbb String ss = "111111"; change2(ss); System.out.println(ss); // 111111 int no = 123; change3(no); System.out.println(no); // 123 Long lon = 1000000L; change4(lon); System.out.println(lon); // 1000000 /** * 在Java中, 对于函数而言, 在函数内部可见的只有形参(实参的COPY), 实参是不可见的. 则在函数内部, 是没有任何方法能修改实参,使指向到一个新的对象. * * 因此, 如果形参是基本数据类型, 则函数执行完成后, 实参的值是不会也无法被改变的. * * 如果形参是引用类型, 则在形参指向到一个新的对象之前的修改, 都会影响到实参(因为此时形参和实参都指向到同一个对象).反之亦然. * */ } public static StringBuffer change1(StringBuffer sb) { sb = new StringBuffer("bbb"); //sb = null; return sb; } public static StringBuffer change11(StringBuffer sb) { sb.append("bbb"); return sb; } public static StringBuffer change12(StringBuffer sb) { sb.append("bbb"); sb = new StringBuffer("ccc"); sb.append("ddd"); return sb; } public static String change2(String str) { str += "1231231"; return str; } public static int change3(int num) { num += 10; return num; } public static Long change4(Long l) { l = l - 11111111111L; return l; } }
相关推荐
spring,cxf,restful发布webservice传递复杂对象,例如List,Map,List<Map>
10个JAVA主题,Item 1:<br> 什么...<br> 避免落入隐藏变量成员的陷阱<br>Item 7: 提前<br>Item 8: <br> 设计可继承的构造函数<br>Item 9: <br> 通过引用传递基本类型<br>Item 10: <br> 布尔运算符与短路运算符本<br>
Java基础教程 教学ppt.<br>苏州职业大学计算机与电子工程系曾海 <br><br>内容如下:<br><br>Java基础教程第十三单元《文件处理》ppt及习题 <br>Java基础教程第十二单元《意外处理》ppt+习题+作业 <br>Java基础教程第...
拆分list,将list<bean>中的内容根据某一属性的值对list进行拆分,分组
简短描述:<br>JAVA做的中文输入法!<br>支持繁体简体,支持粤语国语.<br>跨平台支持!...<br><br><br><br><br> <br>安装步骤:<br>java -jar CantoInput.jar<br><br> <br>测试环境:<br>Linux/Windows<br>提交者:jython<br>
一个C++(Ubuntu16.04+QT5.9.1)通过JNI,调用JAVA类及方法的示例。通过JNI传递和返回多种类型的参数,boolean ,int,String,ArrayList<string>,ArrayList嵌套ArrayList<ArrayList<String>>等。
java 值传递和引用传递的比较区别,包括代码及详解
Java:按值传递还是按引用传递详细解说
MakeJPEG.java<br>4.5. 课程设计作业<br>第5章 标准化考试系统 (单机版)<br>5.1. 设计内容<br>5.2. 设计要求<br>5.3. 总体设计<br>5.4. 具体设计<br>5.4.1. 运行效果与程序发布<br>5.4.2. 主类EnglishTest<br>5.4.3....
第5 版 清华大学出版社<br> “SCJP学习指南” 人民邮电出版社<br> “Java 编程思想” 第3版 机械工业出版社<br> 教学内容和要求<br>知识点 重要程度 使用频度 难度<br>Java 入门 高 中 易<br>变量和运算符 高 ...
我已经把第一学期所有的课件打包在一起了,一共有5部分,这是第一部分<br><br>大家载时要记得评分,这样你们就不要资源分了<br><br>C语言<br><br>HTML && JavaScript 电子档课件ppt.rar<br><br>java&&OOP <br><br>SQL...
<br>北大青鸟第二学期4.0 S2所有资料 四<br><br>我已经把第二学期所有的课件打包在一起了,一共有5部分,这是第四部分<br><br>大家下载时要记得评分,这样你们就不要资源分了<br><br>java WEB <br><br>COT<br><br>sql...
Java搜索引擎的研究与实现(含文档+源码)<br>目录 1<br>摘要 3<br>第一章 引言 4<br>第二章 搜索引擎的结构 5<br>2.1系统概述 5<br>2.2搜索引擎的构成 5<br>2.2.1网络机器人 5<br>2.2.2索引与搜索 5<br>2.2.3 Web...
北大青鸟第二学期4.0 S2所有资料 二<br><br>我已经把第二学期所有的课件打包在一起了,一共有5部分,这是第二部分<br><br>大家下载时要记得评分,这样你们就不要资源分了<br><br>java WEB <br><br>COT<br><br>sql ...
详细描述了Java版<br>和C##版服务器模块的程序设计以及代码清单和解释,Java版和C##<br>客户模块的程序设计以及代码清单和解释;最后,描述了如何开发<br>手持设备的即时消息传递应用程序。 本书内容丰富、讲述层次...
功能主要有: <br><br>* 个人自己下围棋 (意即人和人下围棋) <br>* 落子, 吃子, 及时间的纪录<br>* 自动判断吃子, 打劫, 非法落子, 等等 <br>* 无限步的悔棋功能 <br>* (New!) 棋末记地(算目) (采用日式规则, 是...
不管是按值传递还是按引用传递,都是把栈中的数据备份了一份给参数变量,只不过值类型备份的是具体的数值,而引用类型备份的是内存地址
<br>系统设计<br> 1 jive设计思路 <br> 2 jive的工作内幕 <br> 3 Jive源代码研究 <br> 4 Jive中的设计模式 <br> 5 jive学习笔记 <br><br><br> <br>设计模式<br> 1 大道至简-Java之23种模式一点就通 <br> 2 设计模式...
事情: 从java后台返回List<String>类型数据,用于界面显示。但js中想获取它并操作它。直接使用EL表达式,js把它识别成字符串了。不是我想要的啊。。网上搜了搜大家的解决方案…最好的当然是把List集合转成json格式...
If you want to specify<br>your own output file name use the output redirection:<br><br> jad -p example1.class > myexm1.java<br><br>Option -d allows you to specify another directory for output files,...