//说明输出结果:
public class Example {
String str = new String("good");
char[] ch = {'a','b','c'};
public static void main(String[] args) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str +"and");
System.out.print(ex.ch);
}
public void change(String str, char ch[]){
str= "test ok";
ch[0]= 'g';
}
}
这道题的答案是: good and gbc
很多人都说java不存在引用传递,均为值传递,那我们就这么认为好了。
只是对于java中的基础数据类型byte char int long short float double boolean 在调用方法时传递的是其值,而当你要传递的是一个引用类型时,那么传递的就是他的内存地址(也是一种值)。
那么我们就根据下图来看此题的执行过程:
首先创建Example对象ex,创建String对象str,char[]对象ch,()内为其假设内存地址
那么当我们调用ex的change方法时,流程如下:
首先看change方法中对ch的操作:
ch[0]= 'g';
change方法中的形参ch虽然只是ch引用的副本,但是由于其同样指向该内存地址,因此即使在change()方法执行完毕,形参ch被清除(释放),但还是对原数据进行了修改。
再来看看较为特殊的str:
str= "test ok";
这里涉及到了String类型的不可变性,即String一旦被创建就不可修改,但平时使用中我们会觉得也对字符串进行了修改啊,但是在内存中并不是如此,当执行如下代码时,内存如下图所示:
String str = "hello world";
str = "hello";
由于String类型是不可变的当我们修改str的值时,相当于重新创建了一个新的字符串,并将引用指向新的字符串,原字符串由于不可到达,最终会被GC回收。
那么当执行change方法时,形参str的内存形式如下图:
当change方法执行完毕,该方法被分配的内存空间均得以释放!
而实参str的内存地址依然为3215,那么当输出时,则会输出该内存地址的值。
因此,此题答案为:good and gbc
总结:
在调用方法时,一定要主要区分实参与形参,形参是实参副本,形参在内存里是真实存在的,如本题中的实参str与形参str,虽然同名但却是两个变量(因此形参值的改变对实参没有任何影响),只是形参借用了实参的值而已。当我们调用方法时,形参被创建,当方法执行完成,形参被销毁。