Java基础面试题02:简述什么是值传递和引用传递?

ops/2024/11/26 3:28:58/

面试题:简述什么是值传递和引用传递?

什么是值传递?

值传递(pass by value)是指在调用函数时,把实际参数的值复制一份传递给函数。换句话说,函数内部对参数的任何修改,都不会影响到原始的实际参数。这是因为传递的是“副本”,跟原值没直接联系。

举个例子:

func GetA(b int) int {b++  // 改的是 b 的副本return b
}func main() {a := 1resultA := GetA(a)  // a 的值被复制到 bfmt.Println(resultA)  // 输出 2fmt.Println(a)        // a 还是 1
}

在这个例子中,a的值被复制了一份传给函数GetA,所以函数内部的修改不会影响到外面的a


什么是引用传递?

引用传递(pass by reference)是指直接将实际参数的“地址”传递给函数。函数内的参数变动,会直接影响到实际参数的值,因为函数操作的是原始的“引用”而不是副本。

然而!许多编程语言(比如 Java 和 Go)其实并不是严格意义上的引用传递。它们传递的依然是“值”,只不过这个“值”可能是对象的引用(也就是内存地址的副本)。这点是很多人容易误解的地方。


常见误解,别踩坑!

  1. “值传递是传值,引用传递是传引用。”
    误!问题的关键不在传的是什么,而在于“传递的值有没有被复制”。

  2. “Java 是引用传递。”
    错!Java 传的是引用的副本,是“值传递”。复制了引用,实际参数地址不会被直接修改。

  3. “传递基本类型是值传递,传递对象是引用传递。”
    依然错!语言本质还是值传递,传对象时是引用的值被复制,而不是直接传递引用。


再补充点知识:特殊的“传共享对象调用”

传共享对象有点像引用传递的“拐弯版”。实际参数的地址被复制一份传给函数,操作的是复制后的地址,最后依然指向原始的值。你要改这个值完全没问题,但如果试图改引用本身的指向,就没用。


求值策略的简单解释

求值策略决定了参数在函数调用时是怎么被处理的。这里补充一下最常见的几种:

  1. 传值调用(值传递):
    直接复制参数的值,函数内部改动对实际参数无影响。

  2. 传引用调用(引用传递):
    传的是参数的引用,函数内改动会直接反映到原始参数上。

  3. 传共享对象调用(共享对象传递):
    传递对象的引用副本,操作引用指向的值有效,改引用本身无效。


编程语言中的值传递 VS 引用传递

Go 语言的例子

package mainimport "fmt"func GetB(b int) {b++  // 改的是 b 的副本
}func main() {b := 1GetB(b)fmt.Println(b)  // b 还是 1,因为改的是副本
}

还有字符串的例子:

func subString(str string, start int, end int) (*string, string) {var s = &strsubStr := str[start:end]return s, subStr
}func main() {str := "123,我们"_, result := subString(str, 0, 3)fmt.Println(result)  // 输出 "123"
}

Go 永远是值传递,哪怕传递的是引用,还是复制了引用的副本。


Java 的例子

java">public class Main {public static void main(String[] args) {int a = 1;int b = getA(a);System.out.println(b); // 输出 2System.out.println(a); // a 还是 1}public static int getA(int b) {b++; // 改的是 b 的副本return b;}
}

字符串的例子:

java">public class Main {public static void main(String[] args) {String s = "123,我们";String result = subString(s);System.out.println(result); // 输出 "123"}public static String subString(String str) {return str.substring(0, 3); // 截取字符串,返回一个新字符串}
}

Java 的参数传递本质也是值传递,传递对象时传的是“引用的副本”。


小总结

  • 值传递:传递的是参数的值,函数内修改对实际参数无影响。
  • 引用传递:传递的是参数的引用,函数内修改直接影响实际参数。
  • **Java 和 Go 的参数传递:**都是值传递。传递的可能是值的副本,也可能是引用的副本,但一定是“复制”过的东西。

记住这个逻辑,搞清“传的内容有没有被复制”,以后面试再也不慌啦!

最后说一句(求关注,求赞,别白嫖我)

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。
这是大佬写的
7701页的BAT大佬写的刷题笔记,让我offer拿到手软

本文,已收录于,我的技术网站 cxykk.com:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享

求一键三连:点赞、分享、收藏

点赞对我真的非常重要!在线求赞,加个关注我会非常感激!


http://www.ppmy.cn/ops/136740.html

相关文章

在Excel中处理不规范的日期格式数据并判断格式是否正确

有一个Excel表,录入的日期格式很混乱,有些看着差不多,但实际多一个空格少一个字符很难发现,希望的理想格式是 1980-01-01,10位,即:“YYYY-mm-dd”,实际上数据表中这样的格式都有 19…

Spring Boot教程之五:在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序

在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序 IntelliJ IDEA 是一个用 Java 编写的集成开发环境 (IDE)。它用于开发计算机软件。此 IDE 由 Jetbrains 开发,提供 Apache 2 许可社区版和商业版。它是一种智能的上下文感知 IDE,可用于在各种应用程序…

微服务电商平台番外篇一:常用的docker命令

Docker入门手册 Docker 镜像常用命令 搜索镜像 docker search java 下载镜像 docker pull java:8docker pull macro/eureka-server:0.0.1列出镜像 docker images 删除镜像 docker rmi javadocker rmi -f javadocker rmi -f $(docker images)查看镜像 Docker 容器常用命令…

Java基础-内部类与异常处理

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 一、Java 内部类 什么是内部类? 使用内部类的优点 访问局部变量的限制 内部类和继承 内部…

【JavaEE初阶 — 多线程】定时器的应用及模拟实现

目录 1. 标准库中的定时器 1.1 Timer 的定义 1.2 Timer 的原理 1.3 Timer 的使用 1.4 Timer 的弊端 1.5 ScheduledExecutorService 2. 模拟实现定时器 2.1 实现定时器的步骤 2.1.1 定义类描述任务 定义类描述任务 第一种定义方法 …

Linux ntp时间服务部署

本文使用云服务器,系统是Ubuntu 20.04 LTS,以下操作都是在Ubuntu上面执行的!! 一、Linux系统时间命令 timedatectl命令 timedatectl 是现代 Linux 系统中最强大的时间管理命令,特别是对于使用 systemd 的系统。它不仅…

显示类控件

文章目录 1 QLabel1.1 常用属性1.2 例子1,设置文本 (textFormat)1.3 例子2,设置widget背景图片 (pixmap和scaledContents)1.4 例子3,设置对齐方式 (alignment)1.5 例子4,设置自动换行,缩进和边距1.5.1 设置换行 (wordW…

大连环保公益管理系统|Java|SSM|Vue| 前后端分离

【重要①】前后端源码万字文档部署文档 【重要②】正版源码有问题包售后 【包含内容】 【一】项目提供非常完整的源码注释 【二】相关技术栈文档 【三】源码讲解视频 【其它服务】 【一】可以提供远程部署安装,包扩环境 【…