当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
参考解答
java 中方法传参只有值传递。
首先明确一点,java中的方法调用时,会在方法执行之前把这些参数创建出来,为这些参数分配空间、而每个参数的值,来自于实参的拷贝。例如:
基本类型:
public static void foo(int i){
}
public static void main(String[] args) {
/*
将a的值10拷贝一份,传递给方法参数i
a和i是完全不同的变量,占用不同的内存空间
即使将int i的参数名改为a也一样
*/
int a = 10;
foo(a);
}
引用类型:
public static void foo(User u){
}
public static void main(String[] args) {
/*
将x的引用值拷贝一份,传递给方法参数u
x和u是完全不同的变量,占用不同的内存空间
即使将User u的参数名改为x也一样
*/
User x = new User();
foo(x);
}
更详细的过程分析,请看下面的例子:
例1:
public static void main(String[] args) {
Cat c1 = new Cat();
c1.name = "小黑";
foo(c1);
System.out.println(c1.name);
}
public static void foo(Cat c2) {
c2 = new Cat();
c2.name = "小白";
}
执行过程分析如下:
main方法中执行new Cat() 在堆中分配内存(假设地址为0001),初始化name=null,接下来将引用地址0001赋值给main方法中的c1变量
根据c1变量,引用到堆中0001处的Cat对象,修改name=小黑
接下来调用foo方法,将main中c1变量的值(0001),赋值给foo方法中的c2变量,这里是传值,c1和c2只是引用值一样,引用了同一个堆对象,而它们是独立的变量,占用不同的内存空间
在foo方法中执行new Cat() 会在堆中新分配一块内存(假设地址为0002),初始化name=null,并将引用地址0002赋值给foo中的c2变量,这时c1不会受到任何影响,仍是0001
根据c2变量,引用到堆中0002处的Cat对象,修改name=小白
返回main方法,这时c1变量仍然引用的是0001,因此打印c1.name还是小黑
但 c++ 中是分值传递和引用传递的:
例2 C++值传递:
#include <stdio.h>
void swap(int i, int j) {
int t = i;
i = j;
j = t;
}
int main() {
int a = 23, b = 47;
printf("Before. a: %d, b: %d\n", a, b);
swap(a,b);
printf("After. a: %d, b: %d\n", a, b);
return 0;
}
输出:
Before. a: 23, b: 47
After. a: 23, b: 47
例3 C++引用传递:
#include <stdio.h>
void swap(int *i, int *j) {
int t = *i;
*i = *j;
*j = t;
}
void main() {
int a = 23, b = 47;
printf("Before. a: %d, b: %d\n", a, b);
swap(&a, &b);
printf("After . a: %d, b: %d\n", a, b);
}
输出:
Before. a: 23, b: 47
After. a: 47, b: 23
java中:
例4 java值传递(基本类型):
public static void swap(int a, int b) {
int c = a;
a = b;
b = c;
}
public static void main(String[] args) {
int a = 23;
int b = 47;
System.out.println("Before, a:" + a + " b:"+ b);
swap(a,b);
System.out.println("After, a:" + a + " b:"+ b);
}
输出:
Before, a:23 b:47
After, a:23 b:47
例5 java值传递(引用类型):
public static void swap(Integer a, Integer b) {
Integer c = a;
a = b;
b = c;
}
public static void main(String[] args) {
Integer a = new Integer(23);
Integer b = new Integer(47);
System.out.println("Before, a:" + a + " b:"+ b);
swap(a,b);
System.out.println("After, a:" + a + " b:"+ b);
}
输出仍是:
Before, a:23 b:47
After, a:23 b:47