Java 编程语言中函数传参只有值传递。
先来了解下什么是值传递,什么是引用传递:
参数类型是基本数据类型,是值传递传递过来的是实参的副本,对形参改变不影响实参。
public class Test { public static void main(String[] args) { int n1 = 1; f(n1); System.out.println("n1=" + n1); } private static void f(int n2) { n2 = 2; System.out.println("n2=" + n2); } } /* 运行结果: n2=2 n1=1 */
参数类型是引用类型时,也是值传递,而不是引用传递,传过来的是引用参数的副本,副本里存放的是对象的地址。所以在函数里对地址里的值进行改变时才会影响实参。如果是改变了形参指向的地址,例如new操作,那么实参是不受影响的,还是指向原来的对象地址。
public class Test { public static void main(String[] args) { User n1 = new User(1); f(n1); System.out.println("n1=" + n1.val); } private static void f(User n2) { n2.val = 2; //改变地址里的值 System.out.println("n2=" + n2.val); } static class User { int val; public User(int val) { this.val = val; } } } /* 运行结果: n2=2 n1=2 */
public class Test { public static void main(String[] args) { User n1 = new User(1); f(n1); System.out.println("n1=" + n1.val); } private static void f(User n2) { n2 = new User(2); //指向新地址 System.out.println("n2=" + n2.val); } static class User { int val; public User(int val) { this.val = val; } } } /* 运行结果: n2=2 n1=1 */
所以不要认为形参变实参也变就是引用传递,之所以变是因为传的是实参的拷贝,把实参的值也拷贝给了形参,实参的值就是实际对象的地址,所以形参和实参指向了同一个对象,故通过形参改变了该对象的属性值,那么通过实参访问这个属性也是改变后的。
通过第二个例子可以看到改变了形参指向的地址,这时候形参和实参就指向了不同的对象。
再来看看下面的例子体会下 java 函数传参是值传递,而不是引用传递。
public class Test { public static void main(String[] args) { String s = "abc"; f(s); System.out.println("s=" + s); } private static void f(String s) { s = "cba"; //相当于 s = new String("cba"); System.out.println("s=" + s); } } /* 运行结果: s=cba s=abc */