关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!
看了很多关于阐述JAVA传参到底是值传递还是引用的问题,有些说得很肤浅让人感觉似懂非懂的感觉,但是好像又能解决一些问题,然后就止步了。还有一些则是,讲得很深奥,看着好像很有道理的样子,但是其实还是没怎么懂。
今天再次碰到这个问题时,自己再反思了一下,个人对于一个问题的解决思路,突然觉得大部分人都是碰到问题就去百度,没有去思考这些问题的根本,我们大部分人都缺少独立思考的能力。我一直觉得,所有一切的知识都是一种参考,最最重要的是你以什么方式去保存到大脑里面,是临时的内存保存,还是稍微深刻的硬盘保存,还是再加个快捷方式直达目的?所以,我想以自己的独立思考的方式去分析这个问题。
一,为什么会有这样的问题?
归根到底是学习了C语言的缘故,因为C的指针问题一直是一个比较难啃的骨头,也因为难啃所以就成了考试的难点和重点,于是莘莘学子就去攻占,然而大部分情况大家都知道,学校里学的知识虽然很有用,很基础,但是我们大部分人仅仅用它来考试而已(现在后悔了还来得及!)……到了真正要用完全是两码事,最好的教科书就是百度,而搜索出来的一些“大神”,显然并不是都是大神,至少很多并没有考虑到问题的根本原因,就开始各种摘剪(特别是,当大家碰到问题开始大量搜索文章时就会发现这个问题),而一传十,十传百后,就是各种混乱……
二,怎么解决这个问题?
下面是用于举例的函数

public int change(int i) {
i = 111;
return i;
}
public User change(User user) {
user = new User("Jim","Green");
user.setAge(16);
return user;
}

首先,要明确一点,为什么会有引用?因为有指针!Java有指针吗?表面上是没有,但是你要知道几乎所有的高级语言,底层都是用C写的。Java没有指针这类说法是因为Java把指针封装起来了,减少程序员对指针的复杂的操作,所以Java就没有引用这个概念,然后就出现了网上说的Java的传参都是值传递!这是事实,因为你(这个你是指程序猿而不是JAVA)没机会用到指针呗!然而并没有什么卵用!至少对于你理解内存这一块没任何帮助,因为在Java内部确实是有指针操作的。
三,怎么解释这个问题?
一号问题,值传递到底有什么意思?简单的意思就是你把一个参数传到函数里面去,传进去的是这个参数的值(参数的复制品),而不是这个参数的本身!比如你传了个int a=10;的a到函数里面去,实际是相当于传了个i=a到函数里面去(注意:i是i,a是a,它们是独立存在的!),函数外a是什么还是什么!无论你在函数里面怎么赋值,都不会影响到外面的数!记住仅仅是赋值没有影响!
二号问题,为什么仅仅是赋值没有影响。要解释这个问题,还得回到指针这个原始位置(这个是理解这个问题的根本所在!)。首先对于像int,char,long之类不是对象的基本数据类型,就不说了,因为它们只有赋值操作,所以它们肯定是不会反生任何改变的(参考解释在下面)。
但是对于对象类型的参数,要是离开指针去解释,那没有任何人可以解释,因为这是根本!
依旧拿上面的例子来说,你传入一个User.class类型的参数进来(命名为User tom= new User(“Tom”,“Smith”);)所指的内存是TomMemory。
函数内部就会有一个独立的变量user(注意,不要因为你函数外部有个变量是User user = new User();就把它们当作一样的user!它们不一样!是独立的!)。
此时,传进来那个刻(还没到函数体的时候)是这样的:user -> TomMemory;外部的当然依旧是tom=TomMemory;
1,如果你进行赋值操作,比如例子中的user = new User(“Jim”,“Green”);那就变成了user -> JimMemory,后面对user的任何操作,都是基于JimMemory的操作。然后你返回的user当然也是JimMemory,这跟TomMemory没有任何关系啊!当然也就对函数外的tom没有任何影响。上面说的基本数据类型,也是因为这个原理,赋值使得他们指向了不同的内存,两个独立内存当然就没有什么影响了!
2,如果不是赋值操作,而是set之类的改变传入对象属性的操作,那就生效了!为什么?原理同上!因为进来的时候,它们指向的是同一内存块,user和tom都是指向TomMemory,而你直接通过user的方法去操作这个对象,就是直接操作TomMemory内存块,那当然就有效啦。
结束语
尽量不要让自己的思维局限于某个人所说的话,接受之前要加上一些自己的判断力,至少能让你在保存这部分知识不会产生太多知识碎片!
关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!的更多相关文章
- Java方法传参,测试在方法内部改变参数内容是否会影响到原值
我分了三种类型的参数进行测试 一.基本类型 public static void main(String[] args) { System.out.println("验证基本类型int作为参 ...
- python函数传参和返回值注意事项
函数传参 空参数 定义函数时括号里面没有形参,调用时不用传参. def func(): print('null para.') # 调用 func() 位置传参 规定形参的数量,调用时必须传递相同数量 ...
- 死磕面试系列,Java到底是值传递还是引用传递?
Java到底是值传递还是引用传递? 这虽然是一个老生常谈的问题,但是对于没有深入研究过这块,或者Java基础不牢的同学,还是很难回答得让人满意. 可能很多同学能够很轻松的背出JVM.分布式事务.高并发 ...
- [Java]_函数传参的疑惑与思考
问题来源于leetcode上的两道题 Path Sum I && II,分别写了两个dfs. void dfs(TreeNode node , int sum , ArrayList& ...
- 函数传参传的是啥的思考【java Python】
今天看<java 核心 卷1>的时候,作者提到了函数传参的问题,他提到,java传参,传的是值,而不是引用,然后,函数将要传的实参的值(如果实参是基本数据类型,那么就是值.如果实参是对象, ...
- pytest十一:函数传参和 firture 传参数 request
为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数.比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登录函数就行.但是登录 ...
- pytest_函数传参和firture传参数request
前言为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数. 比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行. ...
- 函数传参和firture传参数request
前言 为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数.比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行.但 ...
- 浅谈对java中传参问题的理解
之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...
随机推荐
- 系统图片uri的问题
调用系统图库会出现两种uri的问题,一个是在文件管理器中的图库中,获取到的地址为:content://media/external/images/media/972 这种格式 另外一种的是系统文件管 ...
- 更改printk打印级别
1.查看当前控制台的打印级别 cat /proc/sys/kernel/printk 4 4 1 7 其中第一个"4"表示内核打印函数printk的打印级别,只有 ...
- Winform窗体
Form窗体是Windows应用程序的基本单元.Form窗体不仅是一个窗口,还是一个容器,窗体内可以放置各种控件来实现各种功能.Form窗体也是对象,在窗体类Form中定义了生成窗体的模板,对窗体类进 ...
- JQuery-遮罩层
HTML <html> <head> <link href="StyleSheet.css" rel="stylesheet" t ...
- Robot Motion 分类: POJ 2015-06-29 13:45 11人阅读 评论(0) 收藏
Robot Motion Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11262 Accepted: 5482 Descrip ...
- Reading package lists... Error! 解决方案
ubuntu 下安装python开发包,执行命令 sudo apt-get install python-dev,报错: Reading package lists... Error! E: Enco ...
- qt中信号与槽机制
一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不 ...
- WebForm上传文件FileUpload
//Button1的点击事件 //FileUpload1.FileName为所传文件的名字. //以DateTime.Now.ToString("yyyyMMddhhmmssms" ...
- Android SDK版本和ADT版本
Android SDK版本和ADT版本 Android早期的版本号有点“混乱”,比如Android 2.2对应的ADT版本为ADT-0.9.9而Android 2.3对应的的ADT版本则突然“跃迁 ...
- 模块"xxxx.dll"已加载,但对DllRegisterServer的调用失败,错误代码为 XXXXXXXXX
WIN7.WIN8 注册 卸载dll 报错: 模块"xxxx.dll"已加载,但对DllRegisterServer的调用失败,错误代码为 XXXXXXXXX 解决方法: 若为 ...