Java 只有值传递!为什么?

Java技术栈 2020-11-07 21:28:28
java 博客园 传递


转自公众号:程序控

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

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

值传递?引用传递?

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

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

(String str) { System..println(str)}

实际参数: 我们调用函数时,函数名后面括号中的参数称为实际参数,如下面例子所示

(String[] args) {
A a = A()a.test()}

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

值传递就是把参数的值给你,调用函数时将实际参数复制一份传递到函数中,这样函数内部对参数内部进行修改不会影响到实际参数;而引用传递就不一样了,它直接把参数的实际地址给调用函数了,函数内部可直接修改该地址内容,会影响到实际参数

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

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

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

Java值传递还是引用传递?

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

(String[] args) {
Fans fans = Fans()t = fans.test(t)System..println(+ t) }
(t) {
t = System..println(+ t) }
//输出
In testIn main

上述代码,在main中定义t的值是1,在函数test中修改了参数t的值为2,这个结果是不是很容易分析出来了呢?test函数并未改变传入的t的值,那按照上面我们的介绍是不是可以得出结论:Java中是值传递

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

= String = (Fans fans) {
fans.= fans.= System..println(+ fans.++fans.)}
(String[] args) {
Fans fa = Fans()fa.test(fa)System..println(+ fans.getA()++fans.getB())}
//输出
In testABnewFans
In mainABnewFans

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

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

(String t) {
t = System..println(+ t)}
(String[] args) {
Fans fans = Fans()String tt = fans.test(tt)System..println(+ t)}
//输出
In test:关注公众号
In main:Java技术栈

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

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

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

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

第三个引用对象是String类型,同样传入的是原参数tt的指向地址0x123456,函数test参数t也是指向0x123456的值,那为什么这个和第二个结果不一样的嘞?重点在于 t="关注公众号"; 这一句本来想尝试着使内容"Java技术栈"改变成"关注公众号",但是无奈,String类型是static final类型的,这个大家应该晓得的不,不晓得的该去补课读读String的源码了,于是变成了 t=new String("关注公众号"),t指向了另一个地址,这个地址的内容是"关注公众号",所以原来的引用tt还是指向原来的地址0x123456,并未改变

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

告诉你,就是值传递,因为我们第二个的验证方法不对,你如果在函数的第一行加上个fans = new Fans();你看看它还输出啥,这就变成和第三个String类似的道理了,改变了函数参数的指向位置,函数外部和函数内部输出就不一样了,函数内部也就不会影响外部了;如果按照应引用传递,即使加了这一句,也应该是函数内外都是输出一样的,况且,这也有悖于引用传递的会改变传入参数的概念

思考

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

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

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

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

最后唠叨

赠人玫瑰,手留余香

如果本文帮助到你了,说明我的下个文章也会帮到你,留个关注吧,么么哒

近期热文推荐:

1.Java 15 正式发布, 14 个新特性,刷新你的认知!!

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。

4.吊打 Tomcat ,Undertow 性能很炸!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

版权声明
本文为[Java技术栈]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/javastack/p/13942377.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云