Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java 02 - 值传递与引用传递

Java 02 - 值传递与引用传递

作者头像
Reck Zhang
发布于 2021-08-11 04:12:49
发布于 2021-08-11 04:12:49
76300
代码可运行
举报
文章被收录于专栏:Reck ZhangReck Zhang
运行总次数:0
代码可运行

值传递与引用传递

几个误区

  1. Java是引用传递.
  2. 值类型是值传递, 引用类型是引用传递.
  3. 所有的都是值传递, 因为引用本质上只有个值, 本质上是指针.
  4. 声明的参数是引用类型, 就是引用传递; 声明的参数是一般类型或者指针的就是值传递.

求值策略(Evaluation Strategy)

首先我们要知道, 值传递和引用传递是一种求值策略(Evaluation Stragtegy), 表示的是调用函数的时候, 对于参数传递方式的描述, 而不是对参数本身类型的描述. 值类型和引用类型是两种内存分配方式, 值类型是在调用栈上分配, 而引用类型是在堆上分配. 一个是描述的内存分配方式, 一个是描述参数求值策略, 二者并无依赖和约束关系.

当我们进行函数调用的时候, 为函数所提供的实参, 可以是常量, 也可以是变量, 甚至可以是其他函数的返回值, 但这些实参的形式都称之为表达式, 求值就是对表达式化简并求解值的过程.

求值策略关注的点在于, 表达式在调用函数的过程中, 求值的实际, 值的形式的选取等问题. 求值的时机, 可以在函数调用之前, 也可以在函数调用之后, 由被调用者自己求值. 这里的调用后求值, 可以理解为lazy load.

我们根据求值时间和传值方式, 对不同的求值策略进行分类:

求值策略

求值时间

传值方式

值传递(pass by value)

调用前

值的结果(原值的副本)

引用传递(pass by reference)

调用前

原值(原始对象, 不生成副本)

名传递(pass by name)

调用后(用到后求值)

与值无关的一个名

值传递与引用传递的区别

我们重点看一下值传递和引用传递的区别, 首先是二者在行为表象上的区别:

-

值传递

引用传递

根本区别

会创建副本

不创建副本

所以

函数中无法改变原始对象

函数中可以改变原始对象

这里所说的改变, 是指把一个变量指向另一个对象, 而不是仅仅改变属性或者成员. 因此我们说Java是值传递, 因为调用时会发生copy, 实参不能指向另一个对象, 而不是说被传递东西的本质是一个value, 毕竟计算机里什么都是value.

因此我们知道, 这些行为与参数本身是值类型还是引用类型无关. 对于值传递, 无论是值类型还是引用类型, 都会在调用栈上创建一个副本, 不同的是, 对于值类型而言, 这个副本本身就是原始值的全部复制, 而对于引用类型而言, 由于引用类型的实例在堆上, 所以栈上只有他的一个引用, 其副本也是这个引用的复制, 而不是整个对象的复制.

因此值类型和引用类型的最大区别在于, 值类型作为参数被复制, 但是这不是值类型的特性, 只是值传递带来的效果, 和值类型本身没有关系.

综上所述, 我们对Java的函数调用方式可以描述为: 参数是通过值传递的方式, 传递的值是一个引用的拷贝.

我们可以通过C++来表现值传递和引用传递:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ByValue(int a) {
    a = a + 1;
}

void ByRef(int& a) {
    a = a + 1;
}

void ByPointer(int* a) {
    *a = *a + 1;
}
int main(int argv, char** args) {
    int v = 1;
    ByValue(v);
    ByRef(v);

    // Pass by Reference
    ByPointer(&v);

    // Pass by Value
    int* vp = &v;
    ByPointer(vp);
}

值得注意的是, 从行为考虑, 才是求值策略的本意. 如果把所有东西都抽象成值, 从数据考虑问题, 那就根本没有必要来引入求值策略这一概念了.

在C#中, 可以通过来ref/out来实现引用传递, 没有ref/out就是值传递.

几个解释

针对于上文的几个误区, 我们来一一进行解释:

  1. 引用传递是指的求值方式, 而不是说Java的参数类型是对对象的引用. 并且Java在函数调用时, 是通过值传递的方式, 传递引用的副本.
  2. 一个是描述的内存分配方式, 一个是描述参数求值策略, 二者并无依赖和约束关系.
  3. 从行为考虑, 才是求值策略的本意. 如果把所有东西都抽象成值, 从数据考虑问题, 那就根本没有必要来引入求值策略这一概念了.
  4. 同2.

Java foreach

Java中的foreach是对迭代到当前的对象进行完全拷贝, 而不是获得他的引用拷贝.

Syntax:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (type var : array) { 
    statements using var;
}

等同于:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (int i = 0; i < arr.length; i++) { 
    type var = arr[i];
    statements using var;
}

因此对当前的对象改动, 并不会改变容器中的实际值, 这是值得注意的.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
多图证明,Java到底是值传递还是引用传递?
开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文。
Bug开发工程师
2021/01/28
6320
多图证明,Java到底是值传递还是引用传递?
java是值传递还是引用传递 知乎_按值调用和按引用调用
最近整理面试题,整理到值传递、引用传递,到网上搜了一圈,争议很大。带着一脸蒙圈,线上线下查了好多资料。最终有所收获,所以分享给大家,希望能对你有所帮助。 首先说下我的感受,这个题目出的很好,但是在 Java 中这个题目是有问题的(在下面我会解释)。并且,有很多结论是 Java 中只有 值传递。我认为这样说不够严谨。当然如果针对 Java 语言本身来讲,Java 中只有 值传递,没有引用传递,是正确的。但是如果针对 值传递,引用传递的定义来说,Java 中还是有引用传递的。下面来分析:
全栈程序员站长
2022/11/03
9660
深入解析js中基本数据类型与引用类型,函数参数传递的区别
版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/article/details/51484506
空空云
2018/09/27
1.6K0
Java-值传递和值引用
参考:https://mp.weixin.qq.com/s/Qp6Cc0mlRLnrToNy5-3zeg java的值传递和值引用是一个普通但重要的内容,今天我们依次来了解一下。
android_薛之涛
2019/01/03
1.7K0
Java的JVM介绍以及java的值传递和引用传递
面试的时候碰到的了一个java基础问题,竟然给问蒙了,回来之后感觉针对这个问题总结一下
包子388321
2020/06/16
1K0
说说Java到底是值传递还是引用传递
首先,我们必须要搞清楚,到底什么是值传递,什么是引用传递,否则,讨论 Java 到底是值传递还是引用传递就显得毫无意义。
沉默王二
2020/04/23
4580
说说Java到底是值传递还是引用传递
为什么Java只有值传递
值传递: 调用函数时,将实参复制一份传给函数,函数中修改参数时不会影响实参 引用传递:调用函数时,将实参的地址传给函数,函数中修改参数会影响实参。 判断是值传递还是引用传递的标准,和传递参数的类型是没有关系的。
Qwe7
2022/04/01
4720
这一次,让你彻底理解Java的值传递和引用传递!
学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java只有值传递,有的博客说两者皆有;这让人有点摸不着头脑,下面我们就这个话题做一些探讨,对书籍、对论坛博客的说法,做一次考证,以得出信得过的答案。
Java团长
2019/06/26
8730
这一次,让你彻底理解Java的值传递和引用传递!
值传递与引用传递
“哥,说说 Java 到底是值传递还是引用传递吧?”三妹一脸的困惑,看得出来她被这个问题折磨得不轻。
沉默王二
2021/06/16
1.2K0
值传递与引用传递
一文读懂 Python 值传递和引用传递
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2024/02/26
2.4K9
一文读懂 Python 值传递和引用传递
为什么大家都说Java中只有值传递?
最近跟Java中的值传递和引用传递杠上了,一度怀疑人生。查了很多资料,加上自己的理解,终于搞清楚了,什么是值传递和引用传递。也搞明白了,为什么大家都说Java只有值传递,没有引用传递。原来,我一直以来的认知都是错误的。。。
烟雨星空
2020/06/16
1.6K0
【Java基础】 Java中是值传递还是引用传递
值传递和引用传递最大的区别是传递的过程中有没有复制出一个副本来,如果是传递副本,那就是值传递,否则就是引用传递。
秋水长天
2024/01/13
1440
java — 值传递和引用传递
  在 Java 应用程序中永远不会传递对象,而只传递对象引用。因此是按引用传递对象。Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数。参数可以是对象引用,而 Java 应用程序是按值传递对象引用的。   Java 应用程序中的变量可以为以下两种类型之一:引用类型或基本类型。当作为参数传递给一个方法时,处理这两种类型的方式是相同的。两种类型都是按值传递的;没有一种按引用传递。  java实际上只有值传递,没有真正意义上的引用传递。 按值传递意味着当将一个参数传递给一
Mister24
2018/05/14
1.5K0
浅析按值传递与按引用传递
下列关于按值传递与按引用传递的描述中,正确的是( )。A.按值传递不会改变实际参数的数值 B.按引用传递能改变实际参数的参考地址C.按引用传递能改变实际参数的内容 D.按引用传递不能改变实际参数的参考地址
田维常
2019/12/17
1.2K0
细说值传递、引用传递和地址传递
形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
闫同学
2023/10/14
2440
JavaScript 按值传递 & 按引用传递
其次,对象的比较并非值的比较:对象的比较均是引用的比较,当且仅当它们引用同一个基对象时,它们才相等。     即使两个对象包含同样的属性和相同的值,它们也是不相等的。各个索引元素完全相等的两个数组也不相等
书童小二
2018/09/03
3.8K0
Java 值传递与引用传递
以下是包含引用的完整博客文章,以markdown格式输出,附带“Java 只有值传递”的相关参考来源。
井九
2024/10/12
1680
Java 值传递与引用传递
Java中的值传递与引用传递详解
方法调用是编程语言中非常重要的一个特性,在方法调用时,通常需要传递一些参数来完成特定的功能。Java语言提供了两种参数传递的方式:值传递和引用传递。
良月柒
2019/03/20
2.1K0
Java中的值传递与引用传递详解
Java 函数调用时值传递还是引用传递?
值传递:函数调用时,传递的参数不是实参本身,而是把参数复制一份,传递到函数中,传递的是一份拷贝。如果参数是基本类型/值类型,那么就是把这个类型拷贝一份传到函数中。如果参数是引用类型,那么拷贝的不是引用类型自身,而是这个引用的持有者。 引用传递:函数在调用时,传递的参数就是实参本身(C#中的 ref 就是这种模式)。
水货程序员
2018/11/12
3K0
你们不要再吵了! Java只有值传递..
对于引用类型 str,赋值运算符只会改变引用中所保存的地址,虽然原来的地址被覆盖掉了,str指向了一个新的对象,但是原来的那个老对象没有发生变化,他还是老老实实待在原来的地方!!!
玖柒的小窝
2021/11/05
4030
你们不要再吵了! Java只有值传递..
相关推荐
多图证明,Java到底是值传递还是引用传递?
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文