解释Java中的值传递

来源:互联网 发布:电脑怎么检查网络 编辑:程序博客网 时间:2024/05/19 16:47

string的例子

String str = "aaa";changeString(str);System.out.println(str);public void changeString(String str) {    str = "bbb";}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

changeString方法里,只是将新复制出来的引用str,指向另外一个字符串常量对象“bbb”,方法体外面的str并不受影响,还是指向字符串常量“aaa”,因此最终打印的还是aaa.

int的例子

上面提到的都是对象,下面看一个基本数据类型的例子

int i = 1;changeInt(i);System.out.println(i);public void changeInt(int i) {   i = 2;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对于基本数据类型,他们没有引用,但是不要忘了,调用函数时,复制的动作还是会做的,执行changeInt(i)时,会将 i 复制到一个新的int上,传给changeInt方法,因此不管changeInt内部对入参做了什么,外面的 i 都不会受影响。最后打印出来的还是1.

值传递和引用传递

上面提到的参数传递过程中的复制操作,说白了,就是 = 操作。把上面那个int例子,做一下方法内联,其实就是这样:

int i = 1;// 方法内联,相当于执行changeInt方法int j = i; // 新建一个和i一样的变量j = 2; //修改j的值,i不变System.out.println(i);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对于基本数据类型,= 操作将右边的变量(R_VALUE)完整的复制给左边的变量(L_VALUE),而对于对象,准确的说,应该是指向对象的引用(就像上面说的myDog),= 操作同样也是将右边的引用完整的复制给左边的引用,两者指向同一个对象实例。 
这个 = 操作,是值传递和引用传递的根本差别,这也导致了值传递和引用传递有以下直观上的差别:

  • 如果参数是值传递,那么调用者(方法体外部)和被调用者(方法体内部)用的是两个不同的变量,方法体里面对变量的改动不会影响方法体外面的变量。而之所以在Java可以在方法体内部改变方法体外部的对象,是因为方法体内部拿到了对象的引用,但是这个引用是和方法体外部的引用属于两个不同的引用的,方法体内部的引用指向别的对象,不会导致方法体外部的引用也指向别的对象。
  • 如果参数是引用传递,那么调用者(方法体外部)和被调用者(方法体内部)用的是两个相同的变量,方法体里面对变量的改动会影响方法体外面的变量。

Java的变量都不是对象

通过上面的讲解,你也知道了一个很重要的点:Java里面的变量,要么是基本数据类型,要么是指向对象实例的引用类型,绝对不会是一个对象

引用传递的替代方法

引用传递有两个好处:

  • 引用传递可以避免调用方法时进行拷贝,尤其是当方法的入参是个大对象时,拷贝会耗费大量的时间和空间,当然,这一点Java已经巧妙地解决了,因为对于对象,拷贝的只是它的引用而已;
  • 引用传递可以对外面的对象进行修改,这也是很多语言支持引用传递的原因。

那么,在Java,要怎么实现“对外面的对象进行修改”类似的功能呢? 
答案是使用返回值,类似这样:

a = doSomeThing(a);
  • 1

当然,如果你只是对一个对象进行修改,然后返回这个对象的新的版本,那么可以考虑把这个方法挪到这个对象里面去,就像这样:

a = a.doSomeThing();
  • 1

还有,如果你是需要返回多个值,不使用引用传递,要如何实现? 
答案是返回一个对象,比如你想修改一个地方的经度和纬度,那么与其传入log和lat两个变量,不如把他们封装到Point对象里面去。

以上,希望对你有所帮助。

原创粉丝点击