如果参数是基本类型,传递的是基本类型的字面值的拷贝。
如果参数是引用类型,传递的是对象引用的拷贝。
所谓值传递指的是将变量的一个备份传过去,当该备份被修改后,不会影响原来变量的值;(传递引用类型最多只能改变变量的参数,原因是方法改变通过copy地址改变变量的参数)
而引用传递指的是将该变量的地址传过去,当值修改后,原来的变量也会相应的修改;
一:搞清楚 基本类型 和 引用类型的不同之处
int num = 10;
String str = "hello";
如图所示,num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。
二:搞清楚赋值运算符(=)的作用
num = 20;
str = "java";
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。
如上图所示,"hello" 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)
第一个例子:基本类型
void foo(int value) {
value = 100;
}
foo(num); // num 没有被改变
第二个例子:没有提供改变自身方法的引用类型
void foo(String text) {
text = "windows";
}
foo(str); // str 也没有被改变
第三个例子:提供了改变自身方法的引用类型
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
builder.append("4");
}
foo(sb); // sb 被改变了,变成了"iphone4"。
第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
builder = new StringBuilder("ipad");
}
foo(sb); // sb 没有被改变,还是 "iphone"。
重点理解为什么,第三个例子和第四个例子结果不同?
下面是第三个例子的图解:下面是第四个例子的图解:
根据Horstmann的《java核心技术》(中文第8版P115-P117)的描述,java中是没有引用传递的,原文摘录如下:
“java程序设计语言总是采用值调用。也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容(若是对象最多改变对象的变量)。”
“有些程序员(甚至是本书的作者),认为java程序设计语言对对象采用的是引用调用,实际上这种理解是不对的。”
总结起来,java中参数传递情况如下: (针对方法中传入的参数而言)
· 一个方法不能修改一个基本数据类型的参数
· 一个方法可以修改一个对象参数的状态
· 一个方法不能实现让对象参数引用一个新对象
eg:
下面使用《java核心技术》的一段代码解释为什么java中不存在引用传递:编写一个交换对象的方法:
Employee a=new Employee("tom", 7000);
Employee b=new Employee("jerry", 4000);
public static void swap(Employee x,Employee y){
//交换两个员工的姓名
Employee temp=x;
x=y;
y=temp;
}
如果java使用的是引用传递,那么swap方法应该可以实现交换两个对象值的效果,然而最终结果是,swap并没有改变存储在a和b中的对象引用。swap方法的参数x,y被初始化为两个对象引用值的拷贝,这个方法交换的是两个拷贝,最终没有实现交换的结果。