Java中方法传递机制,到底是值传递还是引用传递???这个要必要深究一下。
同样,先说
结论
①当形参是基本数据类型的时候,是值传递。
②当实参是引用数据类型的时候,传递的是地址值,同时,**还需要注意:String 和 包装类型的值是不可变的。**比如:String str = “word”; 这个word是在字符串常量池中,不可改变,如果进行了一些操作,是会创建出新的字符串。
案例
public class Case {
public static void main(String[] args) {
//局部变量
int i = 1;
String str = "hello";
Integer num = 200;
int[] arr = {1,2,3,4,5};
MyData myData = new MyData();
//方法调用
change(i,str,num,arr,myData);
//最后 i, str, num, arr, myData 的值分别是多少
System.out.println(i);
System.out.println(str);
System.out.println(num);
System.out.println(Arrays.toString(arr));
System.out.println(myData.a);
// 1 hello 200 {2,2,3,4,5} 11
}
private static void change(int j, String s, Integer n, int[] a, MyData m) {
j += 1;
s += "word";
n += 1;
a[0] += 1;
m.a += 1;
}
}
class MyData{
int a = 10;
}
按照上面给出的结论,并结合画 虚拟机的 堆、栈、方法区等进行推断。
(1)对于基本数据类型i
,因为是值传递,所以i
的值并没有改变,还是1。
(2)对于引用数据类型str
,是传递地址,但是String是特殊的类型,他的值hello
是字符串常量,会放在字符串常量池中,在change()
方法中对这个进行改变的时候,原来的hello
不会改变,而是会新生成一个字符创常量helloword
,然后让s
执行他,但是原来的str
还是指向hello
。
(3)引用类型Integer,也是传递地址。但是他是包装类,和String一样,处理之后是会创建新的 常量,只要局部变量的指向没有改变,那就不会改变。还是200。
(4)数组是引用类型,传递引用。change()
方法通过地址找到这个对象,然后改变了这个对象里面的值,所以结果是: {2,2,3,4,5}。
(5)自定义的引用类型,也是传递地址。该引用的值被修改了,结果是11。
虚拟机示意图:
结论再强调一次:
-
基本类型传递值。
-
引用类型传递地址,即:引用。并且对于String 和 包装类型等引用类,他们是值常量,改变的时候,原来地址指向的值不会改变,会创建新的常量对象。