二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催。我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊!

说句实在话,离读者 trust you 发给我这段信息已经过去 1 周时间了。不是我怠慢,确实是可更新的内容实在是太多了。这不,又有两个读者不约而同地要求我更新一下 Java 到底是值传递还是引用传递方面的文章——其实这个问题我之前是写过的,但现在看起来答案似乎不够尽善尽美,所以打算以面试的角度重写一篇。

七年前,我从温和湿润的苏州回到古色古香的洛阳,抱着一幅“天下我有”的心态“约谈”了几位面试官。其中有一位叫老马,让我印象深刻。因为他当时扔了一个面试题把我砸懵了:说说 Java 到底是值传递还是引用传递吧。

我当时年轻气盛,自认为所有的面试题都能对答如流,没想到被老马“刁难”了——原来洛阳这块互联网的荒漠也有技术专家啊。现在回想起来,脸上不自觉地就泛起了羞愧的红晕:当时真菜!不管怎么说,是时候写篇文章剖析一下值传递还是引用传递的区别了。

将参数传递给方法有两种常见的方式,一种是“值传递”,一种是“引用传递”。C 语言本身只支持值传递,它的衍生品 C++ 既支持值传递,也支持引用传递,而 Java 只支持值传递。

01、值传递 VS 引用传递

首先,我们必须要搞清楚,到底什么是值传递,什么是引用传递,否则,讨论 Java 到底是值传递还是引用传递就显得毫无意义。

当一个参数按照值的方式在两个方法之间传递时,调用者和被调用者其实是用的两个不同的变量——被调用者中的变量(原始值)是调用者中变量的一份拷贝,对它们当中的任何一个变量修改都不会影响到另外一个变量。

而当一个参数按照引用传递的方式在两个方法之间传递时,调用者和被调用者其实用的是同一个变量,当该变量被修改时,双方都是可见的。

Java 程序员之所以容易搞混值传递和引用传递,主要是因为 Java 有两种数据类型,一种是基本类型,比如说 int,另外一种是引用类型,比如说 String。

基本类型的变量存储的都是实际的值,而引用类型的变量存储的是对象的引用——指向了对象在内存中的地址。值和引用存储在 stack(栈)中,而对象存储在 heap(堆)中。


之所以有这个区别,是因为:

  • 栈的优势是,存取速度比堆要快,仅次于直接位于 CPU 中的寄存器。但缺点是,栈中的数据大小与生存周期必须是确定的。
  • 堆的优势是可以动态地分配内存大小,生存周期也不必事先告诉编译器,Java 的垃圾回收器会自动收走那些不再使用的数据。但由于要在运行时动态分配内存,存取速度较慢。

02、基本类型的参数传递

众所周知,Java 有 8 种基本数据类型,分别是 int、long、byte、short、float、double 、char 和 boolean。它们的值直接存储在栈中,每当作为参数传递时,都会将原始值(实参)复制一份新的出来,给形参用。形参将会在被调用方法结束时从栈中清除。

来看下面这段代码:

public class PrimitiveTypeDemo {
    public static void main(String[] args) {
        int age = 18;
        modify(age);
        System.out.println(age);
    }

    private static void modify(int age1) {
        age1 = 30;
    }
}

1)main 方法中的 age 是基本类型,所以它的值 18 直接存储在栈中。

2)调用 modify() 方法的时候,将为实参 age 创建一个副本(形参 age1),它的值也为 18,不过是在栈中的其他位置。

3)对形参 age 的任何修改都只会影响它自身而不会影响实参。


03、引用类型的参数传递

来看一段创建引用类型变量的代码:

Writer writer = new Writer(18, "沉默王二");

writer 是对象吗?还是对象的引用?为了搞清楚这个问题,我们可以把上面的代码拆分为两行代码:

Writer writer;
writer = new Writer(18, "沉默王二");

假如 writer 是对象的话,就不需要通过 new 关键字创建对象了,对吧?那也就是说,writer 并不是对象,在“=”操作符执行之前,它仅仅是一个变量。那谁是对象呢?new Writer(18, "沉默王二"),它是对象,存储于堆中;然后,“=”操作符将对象的引用赋值给了 writer 变量,于是 writer 此时应该叫对象引用,它存储在栈中,保存了对象在堆中的地址。

每当引用类型作为参数传递时,都会创建一个对象引用(实参)的副本(形参),该形参保存的地址和实参一样。

来看下面这段代码:

public class ReferenceTypeDemo {
    public static void main(String[] args) {
        Writer a = new Writer(18);
        Writer b = new Writer(18);
        modify(a, b);

        System.out.println(a.getAge());
        System.out.println(b.getAge());
    }

    private static void modify(Writer a1, Writer b1) {
        a1.setAge(30);

        b1 = new Writer(18);
        b1.setAge(30);
    }
}

1)在调用 modify() 方法之前,实参 a 和 b 指向的对象是不一样的,尽管 age 都为 18。


2)在调用 modify() 方法时,实参 a 和 b 都在栈中创建了一个新的副本,分别是 a1 和 b1,但指向的对象是一致的(a 和 a1 指向对象 a,b 和 b1 指向对象 b)。


3)在 modify() 方法中,修改了形参 a1 的 age 为 30,意味着对象 a 的 age 从 18 变成了 30,而实参 a 指向的也是对象 a,所以 a 的 age 也变成了 30;形参 b1 指向了一个新的对象,随后 b1 的 age 被修改为 30。


修改 a1 的 age,意味着同时修改了 a 的 age,因为它们指向的对象是一个;修改 b1 的 age,对 b 却没有影响,因为它们指向的对象是两个。

程序输出的结果如下所示:

30
18

果然和我们的分析是吻合的。

04、最后

好了,我亲爱的读者朋友,以上就是本文的全部内容了。看完之后,再遇到面试官问 Java 到底是值传递还是引用传递时,就不用担心被刁难了。我是沉默王二,一枚有趣的程序员。原创不易,莫要白票,请你为本文点赞个吧,这将是我写作更多优质文章的最强动力。

如果觉得文章对你有点帮助,请微信搜索「 沉默王二 」第一时间阅读,回复【666】更有我为你精心准备的 500G 高清教学视频(已分门别类)。本文 GitHub 已经收录,有大厂面试完整考点,欢迎 Star。

原文链接:https://www.cnblogs.com/qing-gee/p/12759645.html

Java只有值传递的更多相关文章

  1. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  2. java的值传递笔记

    1. 背景:开发小伙伴突然问我java是值传递还是引用传递,我说当然是值传递,只不过有时候传递一个对象时实际传递的是对象的地址值,所以让人容易产生一种引用传递的假象,貌似在李刚的疯狂java讲义有提到 ...

  3. java是值传递还是引用传递

    首先写一个简便的Employee,以便测试使用. class Employee { private String name; public Employee(String name) { this.n ...

  4. Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结

    这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...

  5. java面试3-对于java中值传递的理解(Hollis)

    这是根据Hollis的直面java内容习得(有兴趣的可以加他微信公众号) 对于初学者来说,要理解java中的值传递很难理解,为什么说java只有值传递?那引用传递呢? java中的错误理解: 错误理解 ...

  6. Java是值传递还是引用传递?

    Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...

  7. 堆栈详解 + 彻底理解Java的值传递和引用传递

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

  8. java的值传递机制

    一.练习:编写Java程序,将二维数组中的行列互调显示出来. 代码1为自己编写: package com.xxgpra.CH6; public class Hangliehudiao_pra4 { p ...

  9. Java只有值传递(Java值传递还是引用传递?)

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10830521.html 一:区分Java数据类型.变量类型 Java数据类型分两种:基本数据类型.引用类型. ...

  10. Java的值传递和引用传递的说法

    学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java ...

随机推荐

  1. Linux内核编译配置脚本

    环境 宿主机平台:Ubuntu 16.04.6 目标机:iMX6ULL Linux内核编译配置脚本 在linux开发过程中熟练使用脚本可以大大简化命令行操作,同时对于需要经常重复操作的指令也是一种备忘 ...

  2. JS012. 变量存储含class、id等其他属性的标签元素(动态渲染DOM结点)

    项目中有一处源码需要用变量存储html标签,包含类名和其他一些属性,再动态地将其渲染到页面上. 看下普通的存储方式: initHtml: function () { var me = this; // ...

  3. SpringBoot-Web-初见

    目录 怎么开发一个网站? 静态资源 找到静态资源的存放目录 扩展自定义路径 首页定制 模板引擎Thymeleaf 员工管理系统-初见 国际化 国际化实现 编写国际化配置类 登陆功能 编写index.h ...

  4. RabbitMQ核心知识总结!

    本文已经收录到github仓库,此仓库用于分享Java相关知识总结,包括Java基础.MySQL.Spring Boot.MyBatis.Redis.RabbitMQ.计算机网络.数据结构与算法等等, ...

  5. 这些解决 Bug 的套路,你都会了不?

    最近整理了我原创的 140 篇编程经验和技术文章,欢迎大家阅读,一起成长!指路:https://t.1yb.co/ARnD 大家好,我是鱼皮. 学编程的过程中,我们会遇到各式各样的 Bug,也常常因为 ...

  6. ysoserial CommonsColletions3分析(2)

    上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链. 其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransf ...

  7. android开发使用jxl创建Excel

    这周水了几天,今天把博客赶上,找找状态. 周五的时候终于完成了课堂测试第二阶段,主要的难点就是生成Excel表并将填写的数据插入到Excel表中. 一.jxl使用 1.创建或读取一个工作薄 Workb ...

  8. java.lang.SecurityException: MODE_WORLD_READABLE错误解决

    问题描述:运行Android项目有以下报错: 解决方法: 把 MODE_WORLD_READABLE 更换成 MODE_PRIVATE 即可,因为MODE_WORLD_READABLE 模式已经被废弃 ...

  9. 【PHP数据结构】链表的相关逻辑操作

    链表的操作相对顺序表(数组)来说就复杂了许多.因为 PHP 确实已经为我们解决了很多数组操作上的问题,所以我们可以很方便的操作数组,也就不用为数组定义很多的逻辑操作.比如在 C 中,数组是有长度限制的 ...

  10. python并发与futures模块

    非并发程序(用于对比) 从网上下载20个国家的国旗图像: import os import time import sys import requests # 导入requests库 POP20_CC ...