探讨Java中函数是值传递还是引用传递问题
作者:taixuyingcai 发布时间:2021-07-25 19:34:44
相信有些同学跟我一样,曾经对这个问题很疑惑。在网上也看了一些别人说的观点,评论不一。有说有值传递和引用传递两种,也有说只有值传递的,这里只说下个人见解
先给大家介绍下概念
值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
引用传递:(形式参数类型是引用数据类型参数):也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
先看一个例子
public class Test1 {
public static void main(String[] args) {
int a = 10;
changeNum(a);
System.out.println("main a=" + a);
}
static void changeNum(int a) {
a = 100;
System.out.println("changeNum a=" + a);
}
}
结果:
changeNum a=100
main a=10
说明对于基本的数值类型其实传递的是一份数值的拷贝,传入函数之后跟原来的值就没有关系了,在函数中改变这个数的值也不会影响到原来的值。
再看一个例子
public class P {
String name = "P";
public P(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public class Test {
static P p1 = new P("p1");
public static void main(String[] args) {
P p = new P("P");
System.out.println("before change p:" + p.toString);
changeObj(p);
System.out.println("after change p:" + p.toString());
}
static void changeObj(P p) {
p = new P("pp");
System.out.println("change p:" + p.toString());
//p = p1;
//System.out.println(p.toString());
}
}
这个例子中的运行结果会是什么呢?
在这个例子中传入的是一个对象类型的数据。
我们先来猜想一下:如果传入的是一个对象的引用,在函数中改变了这个引用所指向的对象,那么外部的引用"p"应该是指向了新创建的P("pp")的对象才对
所以猜想的结果是:
before change p:P
change p:pp
after change p:pp
那让我们来实际运行一下看看结果,实际的结果是:
before change p:P
change p:pp
after change p:P
想猜想的不一样!!!
这就让我们很疑惑了,为什么函数没有改变引用所指向对象呢?
其实是这样的,首先要理解“=”赋值操作的意义,
对于基本类型来说“=”赋值操作是直接改变内存地址上的值,
而对引用类型来说“=”赋值其实是改变引用变量所指向的内存地址。
赋值操作后
引用的赋值并没有对原来的对象造成影响,"hello"对象仍然是存在的,只是str又指向了新的"world"对象
理解了赋值操作后,现在来说下函数的参数传递
函数的参数实际上就是函数内部的一个局部变量,从外部传值给这个参数实际上就是一个赋值的过程。
来看看第一个例子,传一个定义一个int类型名称为a的形式参数,其实完全可以把名称改为b
然后把外部变量a的值传递给函数的变量,就是赋值。基本类型的赋值就是把外部a变量的10赋值给函数变量a,所以这其实是两个变量,两者之间没有任何关系,
所以对函数内部变量的改变也不会对外部的变量造成影响。
再来说下引用类型的传递,其实是一个道理。
在传递的时候是把一个对象的内存地址赋值给函数内部的引用类型的局部变量
如上图所示,两个变量是指向同一个对象的。
在第二个例子中,我们在函数内部新创建了一个对象,并重新赋值给内部变量p,其实是改变了内部变量的引用所指向的对象,如下图所示
所以对外部的p变量是没有影响的。
总结:
函数参数传递其实是一个赋值的过程,基本类型传递的是数值,引用类型传递的引用对象的内存地址。
另外一点要特别注意,函数的参数其实是函数内部的局部变量。不要跟外部变量混淆.
以上所述是小编给大家介绍的Java中函数是值传递还是引用传递问题网站的支持!
来源:http://www.cnblogs.com/taixuyingcai/p/6373423.html
猜你喜欢
- using System;using System.Collections.Generic;using System.Net;using S
- 本文研究的主要是java网络爬虫连接超时的问题,具体如下。在网络爬虫中,经常会遇到如下报错。即连接超时。针对此问题,一般解决思路为:将连接时
- java模拟实现图书检索系统 (基础版),供大家参考,具体内容如下练习实现3个简单的功能,没有优化,可以根据需求,自行添加想要实现的功能。B
- 类加载机制java类从被加载到JVM到卸载出JVM,整个生命周期包括:加载(Loading)、验证(Verification)、准备(Pre
- 背景:用习惯了idea再去用eclipse实在用的不习惯,于是将老的eclipse项目导入到eclipse,网上有很多教程,看了很多博客都不
- 一、redis发布订阅简介Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收信息。可以参
- 本文介绍了Spring Boot Admin监控服务上下线邮件通知,分享给大家,具体如下:微服务架构下,服务的数量少则几十,多则上百,对服务
- 一. 线程池简介1. 线程池的概念:线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建
- 压缩包制作也是很多项目中需要用到的功能。比如有大量的文件(假设有10000个)需要上传,1个1个的上传似乎不太靠谱(靠,那得传到什么时候啊?
- maven没有打包xml文件的问题最近使用maven带管理项目,采用SSM的技术栈,在配置好一些配置文件,打包部署到tomcat上,出现没有
- 1.简介建议阅读本文最好对Dokcer有一些了解首先我们先了解一下Docker是什么Docker 属于 Linux 容器的一种封装,提供简单
- SWT中没有AWT的BorderLayout布局管理器。下面是SWT下的自定义实现: BorderLayout.java package s
- 本文实例讲述了Java实现文件和base64流的相互转换功能。分享给大家供大家参考,具体如下:import java.io.FileInpu
- 一、按钮组件1.1 提交按钮组件package swing;import java.awt.*;import java.awt.event.
- 本文实例为大家分享了Android实现支付宝支付密码输入界面的具体代码,供大家参考,具体内容如下效果图:主要代码:import java.u
- 直接调用Math里面的random即可,简单方便int i = (int)(Math.random()*100+1);
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard
- 一、java方法重写方法的重写是子类根据需求对父类继承的方法进行重新的编写,在重写时,可以使用super方法的方式来保留父类中的方法,注意:
- 接着上一篇再为大家介绍java应用和输入输出常用方法,供大家参考,具体内容如下一、应用1、使用StringBuilder或StringBuf
- IDEA安装后,前进 后退快捷按钮默认不在工具栏显示,需要手动将其添加到工具栏*按照图一选中Toolbar Run Actions ,点击右