面试官:Java为什么只有值传递?

2023-10-27

面试官爱问的一个基础问题:Java是值传递还是引用传递?

想必大家都对这个问题都有自己的看法,那到底事实是怎样的,我们又该如何回答面试官这个问题呢?今天咱们就来好好分析一波

在这里插入图片描述

值传递?引用传递?

首先,我们得先知道什么叫值传递,什么叫引用传递,知道这个才能理解Java到底如何做的。若想理解这两种传递需要先理解形式参数和实际参数两个概念

形式参数:定义函数时使用的参数,用来接收函数传入参数,比如我们写个函数,函数中的参数为形式参数

public void test(String str) { //str为形式参数
    System.out.println(str);
}
实际参数:我们调用函数时,函数名后面括号中的参数称为实际参数,如下面例子所示

public static void main(String[] args) {
    A a = new A();
    a.test("chengxukong");//chengxukong则为实际参数
}

可以发现,当调用一个有参函数的时候,会把实际参数传递给形式参数;于是这个传递的过程便有两种情况,即值传递和引用传递

值传递就是把参数的值给你,调用函数时将实际参数复制一份传递到函数中,这样函数内部对参数内部进行修改不会影响到实际参数;

而引用传递就不一样了,它直接把参数的实际地址给调用函数了,函数内部可直接修改该地址内容,会影响到实际参数

我来举个例子,我司有一个数据库A,仅允许内部人员操作,现在有个项目需要和别的公司合作,该数据库的数据需要交给合作公司一份,我总不能直接把我司数据库A地址给他们,让他们直接连我们数据库A吧,他们要是删库跑路了,那我boss岂不要杀我祭天了
在这里插入图片描述

所以这个时候,把我司数据库表数据拷贝一份到一个新的数据库B,合作公司可以看这个数据库B数据,他们也可以随意操作,不会影响我司数据库

这个操作就类似于值传递,如果合作公司直接操作我司数据库,就类似于引用传递了,这下大家应该晓得两者之别了

Java值传递还是引用传递?

我们了解了值传递和引用传递的概念,那Java中到底是哪种传递方式呢?我们来看代码分析

 public static void main(String[] args) {
    Fans fans = new Fans();
    int t = 1;
    fans.test(t);
    System.out.println("In main:" + t);
 }
 public void test(int t) {
    t = 2;
    System.out.println("In test:" + t);
 }
//输出
In test:2
In main:1

上述代码,在main中定义t的值是1,在函数test中修改了参数t的值为2,这个结果是不是很容易分析出来了呢?

test函数并未改变传入的t的值,那按照上面我们的介绍是不是可以得出结论:Java中是值传递
在这里插入图片描述

有的人可能会质疑,你传入的参数t是基本类型,你若传入引用对象类型,那肯定就会改变对象内容了,OK,再来看一段引用类型代码

int a = 10;
String b = "fans";

public void test(Fans fans) {
    fans.a = 20;
    fans.b = "newFans";
    System.out.println("In test,A:" + fans.a+",B:"+fans.b);
}
public static void main(String[] args) {
    Fans fa = new Fans();
    fa.test(fa);
    System.out.println("In main,A:" + fans.getA()+",B:"+fans.getB());
}
//输出
In test,A20B:newFans
In main,A20B:newFans

哎啊,输出结果竟然一样了,也就是传入的fans对象被函数test修改了,那这样是不是又变成了引用传递了?

在这里插入图片描述

于是得出结论,基本类型是值传递,引用类型是引用传递?事实是这个样子吗,我们再来通过String这个引用类型实验下

public void test(String t) {
    t = "关注公众号";
    System.out.println("In test:" + t);
}
public static void main(String[] args) {
    Fans fans = new Fans();
    String tt = "程序控";
    fans.test(tt);
    System.out.println("In main:" + t);
}
//输出
In test:关注公众号
In main:程序控

啊,这,咋肥事,传递的参数值并未修改,怎么又变成值传递了

上述三个例子表现结果各有差异,到底结论是什么呢?一起来分析下

第一个传入的是基本类型,基本类型指向的就是数值,传递类似于赋值操作,不会对原数值产生影响,就是类似于a=10,b=a,b=20这种,并不会使a变为20;

第二个引用对象传入的是引用类型fans的地址的值,传入的原参数fa指向地址0x123456,所以函数test的参数fans也指向0x123456,函数内部对引用fans进行修改,于是修改了0x123456地址的值,造成外部改变

第三个引用对象是String类型,同样传入的是原参数tt的指向地址0x123456,函数test参数t也是指向0x123456的值,那为什么这个和第二个结果不一样的嘞?

重点在于 t=“关注公众号”; 这一句本来想尝试着使内容"程序控"改变成"关注公众号",但是无奈,String类型是static final类型的,这个大家应该晓得的不,不晓得的该去补课读读String的源码了,于是变成了 t=new String(“关注公众号”),t指向了另一个地址,这个地址的内容是"关注公众号",所以原来的引用tt还是指向原来的地址0x123456,并未改变
在这里插入图片描述

有的同学可能会提出问题了,为什么第二个可以改变这个地址的内容,第三个不行?很明显啊,String是final的,不可修改,而第二个可以直接修改该地址的内容;那问题又来了,既然这样,还能叫值传递吗?

在这里插入图片描述

告诉你,就是值传递,因为我们第二个的验证方法不对,你如果在函数的第一行加上个fans = new Fans();你看看它还输出啥,这就变成和第三个String类似的道理了,改变了函数参数的指向位置,函数外部和函数内部输出就不一样了,函数内部也就不会影响外部了;

如果按照应引用传递,即使加了这一句,也应该是函数内外都是输出一样的,况且,这也有悖于引用传递的会改变传入参数的概念

思考

值传递和引用传递并不是按照传递的内容来区分的,传递的是引用的并不一定的引用传递,根据定义结果来区分;

在Java中用的是值传递(记好咯,下次面试别回答错了)

在其它方法里面改变引用类型的值都是通过引用改变的,当传递引用对象的时候,传递的是复制的引用的对象句柄,是复制过的,也就是在内存中复制了一个句柄,这两个句柄指向同一个对象,所以你改变这个句柄对应的空间的数据会影响到外部的变量

虽然是复制的,但是指向的是同一个地址,当你把这个句柄指向其它对象的引用时并不会改变原来的值(例子三String),因为你用的是复制过的句柄

结束语

感谢大家能够做我最初的读者和传播者,请大家相信,只要你给我一

份爱,我终究会还你们一页情的。

欢迎大家关注我的公众号【左耳君】,探索技术,分享生活

哦对了,后续所有的文章都会更新到这里

https://github.com/DayuMM2021/Java

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试官:Java为什么只有值传递? 的相关文章

  • Java 中等效的并行扩展

    我在 Net 开发中使用并行扩展有一些经验 但我正在考虑在 Java 中做一些工作 这些工作将受益于易于使用的并行库 JVM 是否提供任何与并行扩展类似的工具 您应该熟悉java util concurrent http java sun
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • OPENSSL库的使用-RSA篇

    一 RSA算法简介 RSA公钥加密算法是1977年由Ron Rivest Adi Shamirh和LenAdleman在 美国麻省理工学院 开发的 RSA取名来自开发他们三者的名字 RSA是目前最有影响力的公钥加密算法 它能够抵抗到目前为止
  • 我的GIT练习TWO

    目录 前言 GIT安装教程 Git作者 GIT优点 GIT缺点 为什么要使用 Git GIT练习TWO C1 C2 C3 C4 C5 C6 C7 总结 前言 Git 是一个分布式版本控制及源代码管理工具 Git 可以为你的项目保存若干快照
  • vue3+element-plus上传文件,预览文件

    vue3 ts element plus上传文件 预览文件 场景 使用element plus的el upload标签 手动上传文件 可预览docx xlsx pdf jpg jpeg png 本地资源以及网络资源 1 使用el uploa
  • 三废的日常--Nginx实现负载均衡

    第二天 小废给大废买了杯奶茶 大废 这才差不多 讲了这么多早就应该给我奶茶了 吧唧吧唧 大废 那今天就来讲讲Nginx是如何实现负载均衡吧 二废 这个我知道 我看过Nginx的配置 nginx通过upstream下的配置 对配置的服务器进行
  • Go程序当父进程被kill,子进程也自动退出的问题记录

    平常我们启动一个后台进程 会通过nouhp 的方式启动 这样可以在退出终端会话的时候 进程仍然可以继续在后台执行 进程的父进程id会从原来的bash进程变成1 在go程序中 通过nouhp 的方式启动子进程 预期是即使父进程挂掉 子进程也能
  • 在阿里云CentOS7上搭建ftp服务器

    当我再次被各种出站入站规则玩弄 在搜索引擎的帮助走出泥淖后 我决定记下这次经历 1 FTP服务器的部署 1 1 安装vsftpd 笔者使用的是阿里云的ECS服务器 这不是广告 而是提醒 P 操作系统为CentOS7 首先 安装vsftp v
  • vue下基于elementui自定义表单-后端数据设计篇

    vue下基于elementui自定义表单 后端篇 自定义表单目前数据表单设计是基于数据量不大的信息单据场景 因为不考虑数据量带来的影响 数据表有 1 表单模版表 2 表单实例表 3 表单实例项明细表 4表单审批设计绑定表 以FormJson
  • 软件测试面试题11-接口自动化测试怎么做?

    面试过程中也遇到了这个问题 自己的回答 接口自动化测试 之前做过 第一个版本是用jmeter 做的 1 主要是将P0级别的功能接口梳理出来 根据业务流抓包获取相关接口 并在jmeter中跑通 2 是整理了项目上的所有接口 先将单个接口跑通
  • JDBC连接数据库的方法及注意事项

    Hello 小伙伴们 大家好 1 准备工作 先下载一个JDBC的驱动jar包 就在下面 直接拿去 https dev mysql com downloads connector j 放在新建的Directory文件夹里 一定要与src是同级
  • 重写QTabWidget,在标签后面添加图标按钮

    原本的QTabWidget没有支持在标签后面添加自定义的按钮的方法 想在后面添加自定义的功能按钮需要重写QTabWidget类 自己实现按钮图标的重绘和鼠标点击判断等操作 1 使用到的主要事件函数 1 void paintEvent QPa
  • 钢条切割-递归,记忆性递归,dp

    钢条切割 方法1 递归 import java util Scanner public class Cutting public static int n 10 public static int p 1 5 8 16 10 17 17 2
  • CBU计算机硕士申请难度,电脑开机后CBU百分只百是什么问题

    公告 为响应国家净网行动 部分内容已经删除 感谢读者理解 话题 电脑开机后CBU百分只百是什么问题回答 有几点建议供您参考 一 使用360 优化大师等工具 将系统启动项进行优化 尽量不要自启动不常用的进程 如果不会就选择 一键优化 二 使用
  • assert_param的应用

    在STM32的固件库 到处都可以见到assert param 的使用 一开始见到这玩意就被打蒙了 不晓得它存在的价值 各种查询 理解综合如下 如果打开任何一个例程中的stm32f10x conf h文件 就可以看到实际上assert par
  • 记一次部署发现r2dbc连接数据库问题

    1 背景 a 项目使用R2DBC连接数据库 b 项目在自己搭建环境部署 各种组件使用自己的镜像 没有问题 在客户现场部署 mysql等使用客户服务 发现启动成功后隔几分钟数据库连接被断开 访问数据库报连接超时 2 最终原因 客户数据库服务的
  • go 入门学习 go 语言变量声明方式

    什么是变量 在编程语言中 为了方便操作内存特定位置的数据 我们用一个特定的名字与位于特定位置的内存块绑定在一起 这个名字被称为变量 动静态语言的区别 静态语言有别于动态语言的一个重要特征 变量声明 比如PHP 动态 解释性语言 不必须设定变
  • Unity 透视镜效果 shader模板测试实现 shader学习杂记(一)

    1 透视镜效果示例 场景中创建了三个物体 一个方块 一堵墙 一个球体 然后创建三个材质球 三个初始的shader 将三个shader分别拖给三个材质球 再把材质球拖给三个物体 给这三个物体红色 蓝色 绿色 便于观察 看一下以红色方块为透视镜
  • 成功简易编译cgal

    以前从csdn上下载的cgal 发现下载不了了 索性进行自己编译 用vcpkg 但是编译boost时中间报错 浪费大量时间 从网上查看 很多人都是源码开始编译 这是劝退的节奏么 感谢博主 CGAL编译与配置 尘埃1206的博客 CSDN博客
  • cocos2d-x for android:CCSprite 精灵动画

    setUniformsForBuiltins nodeToParentTransform kmGLGetMatrix KM GL PROJECTION matrixP kmGLGetMatrix KM GL MODELVIEW matrix
  • 数学 {罗尔中值定理}

    数学 罗尔中值定理 罗尔中值定理 定义 条件 函数满足 C a b C a b C a b
  • 面试官:Java为什么只有值传递?

    面试官爱问的一个基础问题 Java是值传递还是引用传递 想必大家都对这个问题都有自己的看法 那到底事实是怎样的 我们又该如何回答面试官这个问题呢 今天咱们就来好好分析一波 值传递 引用传递 首先 我们得先知道什么叫值传递 什么叫引用传递 知