看了很多关于阐述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内存块,那当然就有效啦。
结束语
尽量不要让自己的思维局限于某个人所说的话,接受之前要加上一些自己的判断力,至少能让你在保存这部分知识不会产生太多知识碎片!