前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java中真的只有值传递么?

Java中真的只有值传递么?

作者头像
编程大道
发布于 2020-02-11 09:40:12
发布于 2020-02-11 09:40:12
1.1K00
代码可运行
举报
文章被收录于专栏:编程大道编程大道
运行总次数:0
代码可运行

Java中真的只有值传递么?

(本文非引战或diss,只是说出自己的理解,欢迎摆正心态观看或探讨)

回顾值传递和引用传递

关于Java是值传递还是引用传递,网上有不一样的说法。

1、基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递。 2、Java中只有值传递。

关于这个问题应该是存在争议的。根据测试出来的结果和我们自己的经验,以及口口相传或是上学时老师讲的,我们认为是第一种。但第二种说法的呼声也很高,渐渐地我们也认为第2中才是对的。那么下面我们就来分析一下这个问题。

在谈这个问题之前我们先了解值传递和引用传递的概念及现象。我还记得,值传递和引用传递这些概念是大学里学Java的时候老师教给我的,它们的概念是什么呢?老师是通过例子来讲解的,大概是这样的。

值传递

例子1:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args){
    TestJavaParamPass() tjpp = new TestJavaParamPass();
    int num = 10;
    tjpp.change(num);
    System.out.println("num in main():"+i);
}
public void change(int param){
    param = 20;
    System.out.println("param in change():"+param);
}

控制台输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
param in change():10
num in main():20

mian()方法中的int变量num传递给change()方法,change()方法接收到后将值改变为20。通过看控制台输出,main()方法中的num变量的值没有改变。

结论:基本类型是值传递。

引用传递

例子2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args){
    TestJavaParamPass() tjpp = new TestJavaParamPass();
    User user = new User();
    user.setName("Jerry");
    tjpp.change(user);
    System.out.println("user in mian():"+user);
}
public void change(User param){
    param.setName("Tom");
    System.out.println("param in change():"+param);
}

控制台输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
param in change():User(name=Tom}
user in mian():User(name=Tom}

main()方法中的user变量传递给change()方法,change()方法改变了其name属性值。通过看控制台输出,main()方法中的user变量的name属性值发生改变。

结论:引用类型是引用传递。

特殊的值传递

例子3:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args){
    TestJavaParamPass() tjpp = new TestJavaParamPass();
    String name = "Jerry";
    tjpp.change(name);
    System.out.println("name in main():"+i);
}
public void change(String param){
    param = "Tom";
    System.out.println("param in change():"+param);
}

控制台输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
param in change():Tom
name in mian():Jerry

String也是引用类型的数据类型,为什么值没改变?因为在change()方法里param = "Tom";相当于param = new String("Tom");就相当于param被重新赋值指向了另外一个对象。所以,其实String类型传的是引用,只不过被重新赋值指向了别的对象了,没有修改原对象。即,String本质上还是引用传递,表像上是值传递。

结论:基本类型是值传递,引用类型是引用传递,String是特殊的值传递。

这个结论也是网络上流传的比较多的,可能大部分程序员的认知都是这样的。至于值传递和引用传递的概念,接下来便可根据上面的例子和结论推断出来,以及解释为什么大多数程序员都将String理解为是特殊的值传递。

概念提取

与其叫概念提取好不如叫结论总结呢。

值传递:基本类型的变量在被传递给方法时,传递的是该变量的值(即复制自己的值传递给方法)。

引用传递:引用类型的变量在被传递给方法时, 传递的是该变量的引用(即自己所指向的内存地址)。

为什么说String是特殊的值传递:是因为String和基本类型从表象来说表现出来的结果是一样,大概是为了便于记忆这个结果才这样说的吧。但是要知道String也是引用传递只不过它的引用被重新赋值,指向了别的对象了,所以不会影响原值。所以String不能简单的说是值传递。

解析Java只有值传递的说法

只有值传递的说法

网上还流传一种说法叫Java只有值传递。网上有文章论证了Java只有值传递的说法,其中举的例子和上面的类似。

分析的很透彻,解释了上面三个例子的本质。指出了上面第二个例子的错误之处,举的例子不恰当。并指出下面这样的例子才恰当,又举了钥匙和房子的例子,佐证了上面第2个例子确实不恰当。因为上面的例子的侧重点都是最后实际变量的值有没有改变。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args){
    TestJavaParamPass() tjpp = new TestJavaParamPass();
    User user = new User();
    user.setName("Jerry");
    tjpp.change(user);
    System.out.println("user in mian():"+user);
}
public void change(User param){
    param = new User()
    param.setName("Tom");
    System.out.println("param in change():"+param);
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
param in change():User(name=Tom}
user in mian():User(name=Jerry}

最后文章的结论是Java只有值传递。引用类型大概是这样解释的( 基本类型就不用说了 ),实际变量(实际参数)赋值一份自己的引用地址的值传给方法,方法的形式参数拿到的是实参的引用地址的值。侧重点在值,所以结论说的是引用类型也是值传递。

解析

我觉得论证者分析基本类型和引用类型的实参形参的变化的原理是没有问题的,但是得出的结论是不是有点不恰当。怎么说呢?请继续看。

论证者的意思是,java只有值传递。也就是说引用类型也是值传递,侧重点是复制一份引用的地址的值给形参,在于这里的值是引用的地址的值(不是引用所指向的内存里存的值),所以说是值传递。是不是有点牵强?我觉得有点偷换概念,没错,大家都知道引用类型传递的是引用的值,但你不能因为传递的是值就说是值传递,不传值还能传什么?引用是内存地址,不是也得用值表示么?

而传统的说法:基本类型是值传递(内存里存东西所代表的值),引用类型是引用传递。我觉得这个侧重点是:基本类型把值复制一份传递过去,引用类型把引用复制一份传递过去。侧重点是传递的东西,基本类型传递的东西叫变量的值(变量本身所代表的值),引用类型传递的东西叫引用(引用本身的值,即内存地址),而非引用所指向的内存空间内的值。所以这样理解引用类型传递的是引用也没问题啊。

所以,Java中基本类型传递的是变量所代表的自身的值(内存里存东西所代表的值),是值传递;引用类型传递的是对象的引用,是引用传递;再深一步,引用也是一个确切的值来表示的,或者你把引用看作是对象的值,那也可以说引用类型传递的是对象的值,是值传递。

文章还说了

无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递(call by sharing)。其实Java中的参数传递严格意义上说应该是按共享传递。 按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值)。在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作。如果该值在栈中,那么因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响。如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作。因为传递的是地址的拷贝所以函数内对值的操作对外部变量是可见的。 简单点说,Java中的传递,是值传递,而这个值,实际上是对象的引用。

这里的意思是,不论是基本类型还是引用类型传给函数的是实参的地址拷贝,也就是内存地址,可以说是引用,只不过基本类型在栈中,函数内对参数操作时直接拷贝的值,引用类型的值在堆中,需要先找到它的位置,即地址、引用。最后说java是值传递,而这个值是对象的引用。

看到这明白了么?

地址就是引用,那是不是可以说java是引用传递了?传递的是引用的值,计算机中不全是值吗,不是值还能是什么,说是引用传递是侧重点不同传,传过去的就是地址就是引用,引用不用值表示用啥

这里说的值不是一个概念,说基本类型传的是值,这个是值变量本身的值,说对象传的也是值,这个值说的是引用是地址,而说对象说是引用传递,侧重点在于说是传的地址,指向对象所代表的内部的属性的地址,非对象所表示的内部的属性的值,为的是和基本类型直接传值区分开。

维基百科:引用 (程序设计) 在计算机科学中,引用(英语:reference)是指一个可以让程序间接访问于电脑存储器或其他存储设备中一特定数据的值,该数据可以为变量或记录。 引用和数据本身不同。一般而言,引用会是数据存储于存储器或存储设备中的物理地址。因此,引用亦常被称为该数据的指针地址

看看引用的定义,引用是指一个XXX数据的值。好吧,引用本身就是一个值。但不是值还能是什么呢?计算机中不都是值么?

说值传递还是引用传递都没有错,关键是你怎么定义和解释值传递、引用传递的概念以及值所表示的东西。

计算机中一切皆值,如果从这点出发,那全都是传的值啊,只不过细化到java中,基本类型传递的是自身的值,引用类型传递的是引用的值,而非对象内属性的值。

所以如果武断的说只有值传递也是没问题的,因为在计算机中只能用值来表示啊,但觉得有点投机取巧,就和说世界上只有***,那还区分**和**干嘛,道理差不多。(暂时想不到好的例子哈哈)

还是刚才说的那句,说是引用传递,侧重点在于说是传的是引用是地址,而非对象所表示的内部的属性值,为的是和基本类型直接传值区分开,便于记忆.

最后

最后,大家理解现象的原理即可,没必要追的那么深,或玩文字游戏,钻牛角尖。

如果有人问你,你可以这么说,基本类型和他们的包装类是值传递,引用类型传递的是对象的引用即地址值,String传递的也是地址值,只不过在函数内地址值被修改了,所以不会影响到实参,因表现上和基本类型一样,所以可能为了便于记住这个现象才说String是值传递。归根到底传的都是值只不过值的含义不同。

(本文非引战或diss,只是说出自己的理解,欢迎探讨)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BiggerBoy 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java的传值调用
之所以写这篇文章是因为前些天写了一篇《Java中真的只有值传递么?》探讨了网上关于Java只有值传递的说法,当时写这篇文章的缘由是因为之前看的文章讲解的Java只有值传递,讲的不是让我很明白,没有拿出比较专业的解释或定义,没有说服我。而我在《Java中真的只有值传递么?》这篇文章中又做了一些解读,发现自己也是没有抓住重点,这才有了今天这篇文章,对之前的这篇文章做一个补充。
编程大道
2020/02/11
3.6K0
详解Java中的值传递
如果大家学过c++,那这块肯定是明白的,但是Java中没有引用传递,在编程语言中,将实参传递给方法的方式有俩种就是我们即将要说的,
秋名山码神
2022/12/13
6860
详解Java中的值传递
你们不要再吵了! Java只有值传递..
对于引用类型 str,赋值运算符只会改变引用中所保存的地址,虽然原来的地址被覆盖掉了,str指向了一个新的对象,但是原来的那个老对象没有发生变化,他还是老老实实待在原来的地方!!!
玖柒的小窝
2021/11/05
4030
你们不要再吵了! Java只有值传递..
说说Java到底是值传递还是引用传递
首先,我们必须要搞清楚,到底什么是值传递,什么是引用传递,否则,讨论 Java 到底是值传递还是引用传递就显得毫无意义。
沉默王二
2020/04/23
4580
说说Java到底是值传递还是引用传递
为什么Java中只有值传递【详解】
这里,我们可以清晰地看出x的值在函数执行前后没有发生改变,函数对形参的任何操作,不影响实参;
訾博ZiBo
2025/01/06
680
为什么Java中只有值传递【详解】
Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?
在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。实话实说吧,我就是其中之一。
沉默王二
2019/11/28
5470
Java 02 - 值传递与引用传递
首先我们要知道, 值传递和引用传递是一种求值策略(Evaluation Stragtegy), 表示的是调用函数的时候, 对于参数传递方式的描述, 而不是对参数本身类型的描述. 值类型和引用类型是两种内存分配方式, 值类型是在调用栈上分配, 而引用类型是在堆上分配. 一个是描述的内存分配方式, 一个是描述参数求值策略, 二者并无依赖和约束关系.
Reck Zhang
2021/08/11
7630
这一次,让你彻底理解Java的值传递和引用传递!
学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java只有值传递,有的博客说两者皆有;这让人有点摸不着头脑,下面我们就这个话题做一些探讨,对书籍、对论坛博客的说法,做一次考证,以得出信得过的答案。
Java团长
2019/06/26
8740
这一次,让你彻底理解Java的值传递和引用传递!
为什么大家都说Java中只有值传递?
最近跟Java中的值传递和引用传递杠上了,一度怀疑人生。查了很多资料,加上自己的理解,终于搞清楚了,什么是值传递和引用传递。也搞明白了,为什么大家都说Java只有值传递,没有引用传递。原来,我一直以来的认知都是错误的。。。
烟雨星空
2020/06/16
1.6K0
图说Java值传递原理
Java是一门面向对象的程序设计语言,类是其基本抽象单元,而方法是类中可复用的执行单元;当一个Java方法被调用,方法参数的传递方式究竟是基于值传递还是引用传递呢?答案是:值传递 !
程序猿杜小头
2022/12/01
4840
图说Java值传递原理
面试题系列第7篇:Java方法到底是值传递还是引用传递?
这个问题一直在技术讨论区争论不休。对于初级人员来说很具有迷惑性,即便对于很多高级开发来说,也搞不清楚。本篇文章就带大家探究一下底层的原理,最终化繁为简,让大家通过一两句话就明白到底是值传递还是引用传递。
程序新视界
2020/09/08
1.1K1
解惑4:java是值传递还是引用传递
曾经纠结了很久java的参数传递方式是什么样的,后面粗略的了解了一鳞半爪以后有了大概的印象:“传参数就是值传递,传对象就是引用传递”,后面进一步查找了相关资料和文章以后,发现这么理解是不正确的。
全栈程序员站长
2022/09/23
6530
解惑4:java是值传递还是引用传递
【Java】Java中是值传递还是引用传递的?
在Java当中一个一个方法的调用都是一个入栈的过程,main方法首先入栈,当调用了swap方法的时候swap方法入栈,此时主函数传给swap函数的a和b都会被在swap方法中拷贝出一个副本出来,副本的值的交换不影响主函数中a和b的值。
哈__
2024/04/08
3250
【Java】Java中是值传递还是引用传递的?
难住了同事:Java 方法调用到底是传值还是传引用
byte、short、int、long、float、double、char、boolean 是 Java 中的八种基本类型。基本类型的内存分配在栈上完成,也就是 JVM 的虚拟机栈。也就是说,当你使用如下语句时:
古时的风筝
2020/03/19
1K0
Java 基础概念·Java 只有值传递
当我们调用一个有参函数的时候,会把实际参数传递给形式参数。在程序语言中,这个传递过程中有两种情况,即值传递和引用传递。
数媒派
2022/12/01
4270
Java到底是引用传递还是值传递?
首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。 按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。它用来描述各种程序设计语言(不只是 Java)中方法参数传递方式。
黑洞代码
2021/01/14
8130
Java到底是引用传递还是值传递?
java学习——java按值传递和按址传递
Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)
全栈程序员站长
2022/02/27
6760
探讨Java参数传递问题
可能很多人都知道参数有形参和实参之分,却不知道区别到底是什么;知道Java中内存分为栈、堆、方法区等5片内存,不知道每片内存中保存的都是什么;关于参数的传递到底是值传递还是引用传递傻傻分不清楚。本文将为你逐一揭秘!
贪挽懒月
2018/12/06
9870
探讨Java参数传递问题
java漫谈-Java只有值传递
文中用遥控器(引用)操作电视(对象)为例形象的说明了该引用名词的含义,同时在对定义的“引用”该名词的注释中提到:
WindCoder
2020/01/24
6480
Java的JVM介绍以及java的值传递和引用传递
面试的时候碰到的了一个java基础问题,竟然给问蒙了,回来之后感觉针对这个问题总结一下
包子388321
2020/06/16
1K0
推荐阅读
相关推荐
Java的传值调用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文