1、结论:
- 对象类型传递的是引用:
- 基础数据类型传递的是值,包括int、long、float、double...以及他们的包装类Integer、Long、Float、Double、String...
2、传值和传引用区别:
- 传值:意味着将一个变量传递给一个函数参数时,函数的参数接收的是原始值的一个副本,在函数中对参数的任何改变不会影响原始值;
- 传引用:意味着将一个变量传递给一个函数参数时,函数的参数接收的是原始值的内存地址,而不是值的副本(参数和原始变量指向同一个内存对象),所以对参数的任何修改都会影响原始变量;
实例1:(传值)
void method1(){
int x=0;
this.change(x);
System.out.println(x);
}
void change(int i){
i=1;
}
输出内容仍然为:0
实例2:(传递引用)
void method1(){
StringBuffer x=newStringBuffer("Hello");
this.change(x);
System.out.println(x);
}
voidchange(StringBuffer i){
i.append("world!");
}
输出内容为:Hello world!
实例3:()
1 void method1() {
2 StringBufferx = new StringBuffer("Hello");
3 change1(x);
4 System.out.println(x);
5 }
6
7 void method2() {
8 StringBufferx = new StringBuffer("Hello");
9 change2(x);
10 System.out.println(x);
11 }
12
13 voidchange1(StringBuffer sb) {
14 sb.append("world!");
15 }
16
17 voidchange2(StringBuffer sb) {
18 sb= new StringBuffer("hi");
19 sb.append("world!");
20 }
调用method1(),屏幕打印结果为:"Helloworld!"
调用method2(),我们认为结果应该是"hiworld",因为sb传进来的是引用。可是实际执行的结果是"Hello"!
从内存结构角度去分析change2:
程序执行到第8行,x指向一个存放着"Hello"的内存空间。
变量x---->[存放值"Hello"]
第9行调用change2,将sb指向x指向的内存空间,也就是传入x的引用。
变量x \
-->[存放值"Hello"]
变量sb /
到这里为止还没有什么异样,接下来执行18行,这里就出现了类似传入值拷贝的变化:new方法并没有改变sb指向内存的内容,而是在内从中开辟了一块新的空间存放串"hi",同时sb指向了这块空间。
变量x---->[存放值"Hello"]
变量sb---->[另一块存放"hi"的空间],×原有的引用被切断,接下来再对sb进行append已经和x没有任何关系了。
所以,还有一条不成规则的规则:对于函数调用,最终效果是什么完全看函数内部的实现。比较标准的做法是如果会改变引用的内容,则使用void作为方法返回值;而不会改变引用内容的则在返回值中返回新的值(如本例中的change2不会改变引用内容,所以最好写成StringBuffer change2(StringBuffer sb) {
sb = newStringBuffer("hi");
sb.append("world!");
return sb;
}
)。