Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?

http://www.itpub.net/2019/12/03/4567/
 

在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。实话实说吧,我就是其中之一。

来回顾一下提问者的问题:

我一直认为 Java 是按引用传递的,但是我看一些博客上说不是的。我就纳闷了,Java 到底是值传递还是引用传递?值传递和引用传递有什么区别呢?

如果你也曾被这个问题困扰过,或者正在被困扰,就请随我一起来梳理一下问题的答案。打怪进阶喽!

01、值传递和引用传递

什么是值传递,什么是引用传递?我们需要先把这两个定义搞清楚,才能搞清楚 Java 是按值传递还是按引用传递。

值传递(pass by value)是指在调用方法时将实参复制一份传递到方法中,这样当方法对形参进行修改时不会影响到实参。

引用传递(pass by reference)是指在调用方法时将实参的地址直接传递到方法中,那么在方法中对形参所进行的修改,将影响到实参。

上面是比较官方的定义,读起来不免生硬。在我看来,值传递和引用传递的关键区别有两点:

1)调用方法时有没有对实参进行复制。

2)方法内对形参的修改会不会影响到实参。

what?值传递和引用传递还没有搞清楚,又来两个新名词:实参和形参。别急,别急。

02、实参和形参

实参和形参理解起来比值传递和引用传递容易的多,前者就好像是一元一次方程,后者就像是一元二次方程。

形参:定义方法名和方法体的时候使用的参数,目的是用来接收调用该方法时传入的参数。

实参:在调用有参方法时传入的参数,方法名后面的括号中的参数通常被称为“实参”。

大家应该都写过“hello world”程序了,就像下面这样。

public class Cmower {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

其中 args 就相当于是形参,而字符串“hello world”就相当于是实参。如果觉得这个例子不容易理解,那再来看一个。

public class Cmower {
    public static void main(String[] args) {
        Cmower cmower = new Cmower();
        cmower.sop("沉默王二");
    }

    public void sop(String name) {
        System.out.println("hello " + name);
    }
}

其中“沉默王二”为实参;有参方法 sop(String name) 中的 name 为形参。形参就好像实参与被调用方法之间的一个桥梁,否则调用者没法传递参数,被调用的方法无法接收参数。

03、基本类型是值传递的

Java 中的数据类型可以分为两种,一种是基本类型,一种是引用类型。我相信大家在看本篇文章之前,就能够达成这样一个共识:基本类型是值传递的。这一点毫无疑问。

public class Cmower {
    public static void main(String[] args) {
        Cmower cmower = new Cmower();
        int age = 18;
        cmower.sop(age);
        System.out.println("main 中的 age " + age);
    }

    public void sop(int age) {
        age = 28;
        System.out.println("sop 中的 age " + age);
    }
}

上面这段代码中,sop() 方法的实参 age 为 18,尽管 sop() 方法的形参被修改为 28,但并不会影响实参的值。这一点可以从输出结果中加以证明。

sop 中的 age 28
main 中的 age 18

具体的执行过程如下图所示。

04、引用类型是值传递吗?

大家之所以不确定 Java 是值传递的还是引用传递的,原因就出在这个引用类型上面。单从字面的意思上就容易搞混:引用类型不是引用传递难道还是值传递?

public class Cmower {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        Cmower cmower = new Cmower();
        cmower.setName("沉默王二");
        cmower.sop(cmower);
        System.out.println("main 中的 cmower " + cmower.getName());
    }

    public void sop(Cmower cmower) {
        cmower.setName("沉默王三");
        System.out.println("sop 中的 cmower " + cmower.getName());
    }
}

在 main() 方法中,我们通过 new 关键字创建了一个对象 cmower,并将其 name 属性设置为“沉默王二”;然后将实参 cmower 传递给 sop() 方法,在 sop() 方法中将形参 cmower 的 name 属性修改为“沉默王三”。输出结果是什么样子呢?

sop 中的 cmower 沉默王三
main 中的 cmower 沉默王三

呀!实参 cmower 的属性 name 竟然不是“沉默王二”而是“沉默王三”了!看看,看看,Java 不是值传递吧?

别急别急。我们在 main 方法中追加几行代码。

Cmower cmower = new Cmower();
cmower.setName("沉默王二");

Cmower old = cmower;
cmower.sop(cmower);
System.out.println("main 中的 cmower " + cmower.getName());

System.out.println(old == cmower);

old == cmower 会是 true 还是 false 呢?闭上眼睛想一想。如果实在是想不出,抛一枚硬币吧,反正不是 true 就是 false。假如引用类型是引用传递的,根据引用传递的定义(形参的修改将会影响到实参),那么结果一定就是 false。

我们来看一下输出结果:

sop 中的 cmower 沉默王三
main 中的 cmower 沉默王三
true

true?开什么玩笑?

不好意思,没有开玩笑。Java 的确是值传递的。只不过,引用类型在调用有参方法的时候,传递的是对象的引用,并不是对象本身。而对象的引用在传递的过程中并没有发生改变,虽然对象本身发生了变化。可以通过下面这幅图感受一下。

这下理解了吧?

05、总结

来看下面这段代码。

int age = 18;
String name = "沉默王二";

age 是基本类型,所以值就直接保存在变量中;而 name 是引用类型,变量中保存的只是对象的内存地址,这种变量一般称之为对象的引用。

基本类型作为参数被传递时肯定是值传递;引用类型作为参数被传递时也是值传递,只不过“值”为对应的引用。

[转帖]Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?的更多相关文章

  1. Stack Overflow上59万浏览量的提问:为什么会发生ArrayIndexOutOfBoundsException?

    在逛 Stack Overflow 的时候,发现了一些访问量像昆仑山一样高的问题,比如说这个:为什么会发生 ArrayIndexOutOfBoundsException?这样看似简单到不值得一问的问题 ...

  2. Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?

    在逛 Stack Overflow 的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较 Java 的字符串?访问量足足有 370万+,这不得了啊!说明有很多很多的程序员被这个问题困 ...

  3. Stack Overflow 上人气最旺的 10 个 Java 问题

    1. 为什么两个(1927年)时间相减得到一个奇怪的结果? (3623个赞) 如果执行下面的程序,程序解析两个间隔1秒的日期字符串并比较: public static void main(String ...

  4. 关于Stack Overflow上ASP.NET最大连接数限制提问的一个思考

    原文地址:Why request queuing is high even when request executing is below its limit? We are using below ...

  5. Stack Overflow上关于Java Collections的几个常见问题

    下面列出Stack Overflow上最常见的几个关于Java Collections的问题并给出答案. 1. 什么时候用LinkedList,什么时候用ArrayList? ArrayList是使用 ...

  6. 为什么开发者热衷在Stack Overflow上查阅API文档?

    摘要:一项新研究跟踪了Android开发者的访问历史,发现开发者多达二分之一的文档是从Stack Overflow上获取到的,而Stack Overflow上的示例也多于官方指南,开发者通过搜索更多时 ...

  7. Stack Overflow 上排名前十的与API相关的问题

    Stack Overflow是一个庞大的编程知识仓库,在Stack Overflow 上,数百万的提问被回答,并且这些回答都是高质量的.这就是为什么在Google搜索结果的排行榜上,Stack Ove ...

  8. JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的

    JavaScript超越了Java,c,python等等成为Stack Overflow上最热门的标签 在2015年6月至今,JavaScript超越了Java,c,python等等成为Stack O ...

  9. Stack Overflow 上 250W 浏览量的一个问题:你对象丢了

    在逛 Stack Overflow 的时候,发现最火的问题竟然是:什么是 NullPointerException(java.lang.NullPointerException),它是由什么原因导致的 ...

随机推荐

  1. ubuntu14 谷歌输入法

    sudo apt-get install ibus-googlepinyin 装完重启即可: (在右上角语言处右键,添加text entry)

  2. 文字沟通工具使用SignalR,跨域例子源代码

    其他网站已经有很多关于SignalR的介绍了.这里不多介绍. 安装:Install-Package Microsoft.AspNet.SignalR -Version 1.1.4 参考自:http:/ ...

  3. CSS3属性box-shadow使用教程,css3box-shadow

    CSS3的box-shadow属性可以让我们轻松实现图层阴影效果.我们来实战详解一下这个属性. 1. box-shadow属性的浏览器兼容性先来看一个这个属性的浏览器兼容性: Opera: 不知道是从 ...

  4. 工具批处理Demo

    前言:用C语言写一些小型工具时,使用传递参数的方式会比较方便.如GIF文件转换为头文件工具,如果我们需要将某一个文件夹里所有的gif文件都转换为头文件,这时我们用批处理给这个工具传递参数,会方便很多. ...

  5. zoj 3490

    蛋都疼了,高了半天,Output Limit Exceeded 原来是输入的问题,我靠!!以后还是用输入输出c++好,这尼玛!!郁闷!!!!! #include<stdio.h> #inc ...

  6. 设计模式--MVC(C++版)

    MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式.这种模式用于应用程序的分层开发. Model(模型)-是应用程序中用于处理应用程序数据逻辑的部分.通常模型对象 ...

  7. c# 第一节课 一些简单的应用

    注册要钱 我没钱

  8. centos7忘记root密码重置

    1.重启服务器,选择内存按“e”编辑 2.找到下入内容 3.将上图中标记的ro改为rw init=/sysroot/bin/sh 4.按Ctrl+x进入单用户模式 5.执行命令chroot /sysr ...

  9. winform菜单栏、工具栏

    MenuStrip:菜单 -第一格为选项名,子单可隐藏 --在其中键入”-”可出现分割线或在其上-右键-插入- Sparator -右键-插入标准项,可输入基本菜单项 -右键选项卡--设置图像 --设 ...

  10. HDFS之FileSystem

    package cn.hx.test; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; impo ...