docs/basics/object-oriented/java-pass-by.md
关于Java中方法间的参数传递到底是怎样的、为什么很多人说Java只有值传递等问题,一直困惑着很多人,甚至我在面试的时候问过很多有丰富经验的开发者,他们也很难解释的很清楚。
我很久也写过一篇文章,我当时认为我把这件事说清楚了,但是,最近在整理这部分知识点的时候,我发现我当时理解的还不够透彻,于是我想着通过Google看看其他人怎么理解的,但是遗憾的是没有找到很好的资料可以说的很清楚。
于是,我决定尝试着把这个话题总结一下,重新理解一下这个问题。
关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同,甚至很多人理解的是错误的。还有的人可能知道Java中的参数传递是值传递,但是说不出来为什么。
在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了。如果你有以下想法,那么你有必要好好阅读本文。
错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递。如果是个引用,就是引用传递。
错误理解二:Java是引用传递。
错误理解三:传递的参数如果是普通类型,那就是值传递,如果是对象,那就是引用传递。
我们都知道,在Java中定义方法的时候是可以定义参数的。比如Java中的main方法,public static void main(String[] args),这里面的args就是参数。参数在程序语言中分为形式参数和实际参数。
形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。
简单举个例子:
public static void main(String[] args) {
ParamTest pt = new ParamTest();
pt.sout("Hollis");//实际参数为 Hollis
}
public void sout(String name) { //形式参数为 name
System.out.println(name);
}
实际参数是调用有参方法的时候真正传递的内容,而形式参数是用于接收实参内容的参数。
我们说当进行方法调用的时候,需要把实际参数传递给形式参数,那么传递的过程中到底传递的是什么东西呢?
这其实是程序设计中**求值策略(Evaluation strategies)**的概念。
在计算机科学中,求值策略是确定编程语言中表达式的求值的一组(通常确定性的)规则。求值策略定义何时和以何种顺序求值给函数的实际参数、什么时候把它们代换入函数、和代换以何种形式发生。
求值策略分为两大基本类,基于如何处理给函数的实际参数,分位严格的和非严格的。
在“严格求值”中,函数调用过程中,给函数的实际参数总是在应用这个函数之前求值。多数现存编程语言对函数都使用严格求值。所以,我们本文只关注严格求值。
在严格求值中有几个关键的求值策略是我们比较关心的,那就是传值调用(Call by value)、传引用调用(Call by reference)以及传共享对象调用(Call by sharing)。
不知道大家有没有发现,其实传共享对象调用和传值调用的过程几乎是一样的,都是进行"求值"、"拷贝"、"传递"。你品,你细品。

但是,传共享对象调用和内传引用调用的结果又是一样的,都是在被调函数中如果改变参数的内容,那么这种改变也会对调用者有影响。你再品,你再细品。
那么,共享对象传递和值传递以及引用传递之间到底有很么关系呢?
对于这个问题,我们应该关注过程,而不是结果,因为传共享对象调用的过程和传值调用的过程是一样的,而且都有一步关键的操作,那就是"复制",所以,通常我们认为传共享对象调用是传值调用的特例
我们先把传共享对象调用放在一边,我们再来回顾下传值调用和传引用调用的主要区别:
传值调用是指在调用函数时将实际参数复制一份传递到函数中,传引用调用是指在调用函数时将实际参数的引用直接传递到函数中。

所以,两者的最主要区别就是是直接传递的,还是传递的是一个副本。
这里我们来举一个形象的例子。再来深入理解一下传值调用和传引用调用:
你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。
这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。
你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。
这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。
前面我们介绍过了传值调用、传引用调用以及传值调用的特例传共享对象调用,那么,Java中是采用的哪种求值策略呢?
下一篇我们深入分析。