按值传递和按引用传递

简介:按值传递和按引用传递有什么区别?

关于这两个概念,其实主要来自于程序设计中一个叫“求值策略”的概念。这个概念在百度百科中可以查到:

image.png

百度百科上这段话的说辞上很绕很拗口,这块不用纠结,只要知道一点:这个求值策略下面分两大类:严格的和非严格的;其中严格的下面就有“值传递、引用传递”的概念介绍。

根据该词条的介绍可以发现其实关于求值策略的具体方式有很多中,很多其他的可能压根儿都没有听说过,这里可以忽略掉,但是我在查阅过程中看到了三个比较熟悉的实现方式:传值调用、传引用调用、传共享对象调用

这里面所谓的传值调用其实就是我们常说的值传递,传引用调用就是我们说的引用传递,不过多出了一个传共享对象调用。

传值调用

这种模式我们熟悉的C语言就在使用,这种模式下,实际参数被求出的值是被绑定到了被调函数中对应的变量上,通常都是把整个数据copy一份到新的内存区域中做副本,这时候被调函数内部如果对这个变量进行了调整,也只是在copy后的副本区域上进行了调整,不会影响源参数。

传引用调用

这种模式下,传入到函数内的是实际参数的隐式引用,而并非把整个实际参数的内容全部拷贝到新的内存区域上;如果在被调函数内部对变量进行了修改,对调用方是可见的。

有一些语言支持使用某种方式来实现传引用调用,但是很少有语言是默认使用该方案的,比如C++等都是默认值传递。

而对于像C语言这种,它实际上是通过指针的方式,来模拟传引用调用的效果(因此也会被称为:传地址调用)。

传共享对象调用

此方式由 Barbara Liskov 命名,并被 Python、Java(对象类型)、JavaScript、Scheme、OCaml 等语言使用。

与传引用调用不同的一点在于:调用者传入变量到被调函数内的参数,如果有赋值操作,并不会影响调用者那边变量。

但是如果被调函数内部对传入的参数对象内部做了调整,那么会直接影响到调用方那边,举个例子:

public void test1() {
    Person p1 = new Person("张三");
    test2(p1); // 执行完test2之后,p1仍旧指向张三
    test3(p1); // 执行完test3之后,p1内部name属性就变成了王五
}

public void test2(Person p) {
    p = new Person("李四");
}

public void test3(Person pp) {
    pp.setName("王五");
}

执行完test2之后的示意图:

image.png

执行完test3之后的示意图

image.png

比较在 Java 编程中传递参数的不同方式

在Java中根据数据类型的不同,可能表现有两种不同的穿参形式:

  • 对于基础数据类型的传参,使用的是传值调用,也就是说在参数从调用方传入到被调函数时,会完整复制一份数据拷贝,被调函数内部的所有修改都是修改的拷贝后的副本

  • 对于引用数据类型,它的表现更偏向于传共享对象调用,而非传的沸沸扬扬的传引用调用。

使用按值调用和按引用调用有什么好处?

按值调用

数据完全拷贝一份,这样不用担心被调函数内部对数据做修改,所有的内部修改,影响范围仅限于被调函数内部,出了方法后,调用方仍旧还是持有之前的数据内容。

按引用调用

这种的好处就是可以在被调函数内部影响调用者,对于有些应用场景是很有必要的,有时候有些数据比较复杂,需要单独的方法去做加工处理,处理后的参数可以直接反映到调用者那里,方便快速,同时也省去了复制拷贝所需的空间存储,因为这类对象一般都属于大对象,复制一份既费时也费空间,不划算。

结论

  • 在Java中,既有传值调用,同时也有传共享对象调用。

  • 所谓的传引用调用很少有语言会默认开启它,同时有些语言并非是直接支持传引用调用,而是会通过一些其他的方式来间接达到传引用调用的效果,比如:C语言的指针,有时候会被称为传地址调用

  • 传值调用需要完整拷贝数据,开辟新的内存空间来存储;

  • 传引用调用无需整个拷贝数据,调用方和被调函数共享同一个数据引用

  • 传共享调用和传引用调用类似,不过不同的地方在于:被调函数内部如果对入参进行了赋值操作,则不影响调用方;只有被调函数内部对入参对象内部做了调整才会影响到调用方。

  • Java中基础数据类型参数在方法调用传入时,是使用传值调用的方案;而对于引用类型,则是传共享对象调用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容

  •     关于Java中方法间的参数传递到底是怎样的、为什么很多人说Java只有值传递等问题,一直困惑着很多人,甚至...
    莫生人阅读 188评论 0 1
  • 最近在学习feign时,看了一些源码,其中有一段涉及到==的代码,于是复习了一下java中值传递和值引用的知识点代...
    沫小呆的陌小二阅读 299评论 0 0
  • 一、概述 Java中数据类型分为两大类,基本类型和引用类型。相应的,变量也有两种类型:基本类型和引用类型。 1️⃣...
    Djbfifjd阅读 1,033评论 0 5
  • 值传递: 方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相...
    mrjunwang阅读 302评论 0 0
  • 数据类型 首先了解一下Java中的数据类型数据类型: 基本类型 对象类型 对应的,变量类型: 基本类型包括byte...
    34sir阅读 212评论 0 0