Java面试基础问题之(三)—— Java的值传递

Java中的数据类型可以归为两大类:基本类型和引用类型,前者不用多说,boolean,byte,char short,int,long,float,double 8种基本类型,后者即为所有的类,当然,数组也可以归为类。

基本类型不用讨论,就是值传递(值拷贝),方法中对值的改变不影响原参数的值,下面重点探讨引用类型的参数传递方式。

        先看一个例子:

测试类:

测试类的两个方法:

changeReference ():

changeProperty ():

测试代码及结果:

 

可以“神奇”地发现,changeReference ():竟然没有改变p1的值。

之所以用神奇这个词,因为长期受Java“一切皆对象”的洗脑,想当然认为Java方法的参数传递相当于“引用传递”(C++的知识),即方法中所有对引用的操作都会影响对象本身。而很明显,现在结果告诉我们不是那么回事。

分析之前这里插一句话,实际运用中基本只会用到changeProperty()方式:

谁没事会去传一个对象的引用,然后在方法中对引用本身(而不是对其所指的对象)进行操作(也只有重新赋值这一个操作)呢,就算有此需求,也会将此变量设计为类的属性field,在方法中改变(如setter和getter),不会这么麻烦地传进去再操作。

不管怎么说,找这么多的借口,现在事实摆在眼前:p1没有改变。

原因先摆上:Java中,引用类型的传递方式也是值传递

即在调用:

时,是先对p1进行了一份拷贝,同样指向Tom,在changeReference () 中是对这份拷贝进行了重定向,如下图 :   

而p1并没有任何改变,这一点可以通过打印p1前后的hashCode(直接打印p1调用默认的toString()即可)得到验证:前后是一样的,而在changeReference()内部打印的p(p = new Person("Jerry");之前和之后都输出一下p),会发现前后是不一样的。(PS:由于此处是后来的编辑,所以打印代码就不实验了)

 

再看一例:数组引用的参数传递

测试类:

测试类的两个方法:

changeReference(Person[] p):

changeElement(Person[] p):

测试及结果:

有了上一例的基础,很好理解p1的值为什么没有改变:传入changeReference(Person[] p)方法的仅仅是p1值的一份拷贝,方法体中对该拷贝数组引用本身的改变当然不会影响到原数组。

不过,鉴于数组的特殊性,还是要深究一下原理,先看 p1结构:

如上图,对象数组中实际上存的是对象引用,即对象数组实际上是对象引用数组,那么数组名(此处为p1)可以称为“引用数组的引用”,此时:

就很好理解了,如下图

其中红色是原始的p1,蓝色是changeReference(Person[] p)进行的改变,可以看到,改变之后的p2内容没人任何变化。

而changeElement(Person[] p):

p[0]和p[1]就是指向原对象Person("a")和Person("b")的引用,现在对其新的赋值,所以上面的代码就类似于上一例子中:

即将对象引用本身改变了,不同的是,这里的对象引用没有使用值拷贝,而且外面“套了”一层数组,这样通过数组首地址指针p,再次访问到对象引用p[0],p[1]时,就不是原来的p[0],p[1](Person("a")和Person("b"))了,如下图示:   

其中红色是原始的p2,蓝色是changeElement(Person[] p)进行的改变,可以看到,改变之后的p2的地址没有变化,但数组元素所引用的对象变化了。

故,综上可以总结出一句话:

“Java只有值传递

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值