我们提供安全,免费的手游软件下载!
在Java编程中,经常会遇到一个问题,即Java是值传递还是引用传递?通过代码层面的实现,我们可以深入探讨这个问题。
让我们从一个简单的代码示例开始,执行下面的代码:
public static void main(String[] args) {
int num = 10;
String name = "Tom";
modify(num, name);
System.out.println("第3次打印int:" + num);
System.out.println("第3次打印String:" + name);
System.out.println("------------------------------------");
}
public static void modify(int n, String str){
System.out.println("第1次打印int:" + n);
System.out.println("第1次打印String:" + str);
System.out.println("------------------------------------");
// 尝试在方法内部修改传进来的参数
n = 999;
str = "ABC";
System.out.println("第2次打印int:" + n);
System.out.println("第2次打印String:" + str);
System.out.println("------------------------------------");
}
打印结果如下:
第1次打印int:10
第1次打印String:Tom
------------------------------------
第2次打印int:999
第2次打印String:ABC
------------------------------------
第3次打印int:10
第3次打印String:Tom
------------------------------------
从结果可以看出,无论是基本类型还是引用类型,在传入方法的参数值和方法执行后的值是一样的。
接下来,我们换个方法将参数取出并返回。
public static void main(String[] args) {
int num = 10;
String name = "Tom";
int modifiedNum = modifyAndReturn(num);
String modifiedName = modifyAndReturn(name);
System.out.println("打印num:" + num);
System.out.println("打印name:" + name);
System.out.println("------------------------------------");
System.out.println("打印modifiedNum:" + modifiedNum);
System.out.println("打印modifiedName:" + modifiedName);
}
public static int modifyAndReturn(int n){
System.out.println("modifyAndReturn第1次打印int:" + n);
// 尝试在方法内部修改传进来的参数
n = 999;
System.out.println("modifyAndReturn第2次打印int:" + n);
System.out.println("------------------------------------");
return n;
}
public static String modifyAndReturn(String str){
System.out.println("modifyAndReturn第1次打印String:" + str);
// 尝试在方法内部修改传进来的参数
str = "ABC";
System.out.println("modifyAndReturn第2次打印String:" + str);
System.out.println("------------------------------------");
return str;
}
得到的结果为:
modifyAndReturn第1次打印int:10
modifyAndReturn第2次打印int:999
------------------------------------
modifyAndReturn第1次打印String:Tom
modifyAndReturn第2次打印String:ABC
------------------------------------
打印num:10
打印name:Tom
------------------------------------
打印modifiedNum:999
打印modifiedName:ABC
通过返回值,我们可以看到参数的改变被成功地保留了下来。接下来,我们对代码进行进一步测试。
public static void main(String[] args) {
int num = 10;
String name = "Tom";
// 打印num和str的地址
System.out.println("修改前,传参前:");
System.out.println(System.identityHashCode(num));
System.out.println(System.identityHashCode(name));
System.out.println("---------------------------");
printAddr(num, name);
System.out.println("---------------------------");
System.out.println("修改后,执行完方法后:");
System.out.println(System.identityHashCode(num));
System.out.println(System.identityHashCode(name));
}
public static void printAddr(int n, String str){
// 打印n和str的地址
System.out.println("修改前,传参后:");
System.out.println(System.identityHashCode(n));
System.out.println(System.identityHashCode(str));
n = 999;
str = "ABC";
// 打印n和str的地址
System.out.println("---------------------------");
System.out.println("修改后,传参后:");
System.out.println(System.identityHashCode(n));
System.out.println(System.identityHashCode(str));
}
执行结果如下:
修改前,传参前:
1324119927
990368553
---------------------------
修改前,传参后:
1324119927
990368553
---------------------------
修改后,传参后:
1096979270
1078694789
---------------------------
修改后,执行完方法后:
1324119927
990368553
可以看到,传参进来的参数地址与外部定义的地址是相同的,但在修改后会指向另一个新的地址,导致原始地址上的数据不会受到影响。这实际上是一种保护机制,防止方法内部修改参数指向。
接下来,我们演示引用类型的另一种情况。
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
执行以下代码,我们可以看到传入的参数属性被改变:
public static void main(String[] args) {
Person person = new Person("Rosy", 24);
String[] strings = {"AAA", "BBB", "CCC"};
System.out.println("第1次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
modifyObjAndPrintValue(person, strings);
System.out.println("---------------------------");
System.out.println("第4次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
}
public static void modifyObjAndPrintValue(Person person, String[] strings){
System.out.println("---------------------------");
System.out.println("第2次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
person.setAge(1024);
person.setName("ABC");
strings[0] = "XXX";
System.out.println("---------------------------");
System.out.println("第3次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
}
执行结果为:
第1次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第2次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第3次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]
---------------------------
第4次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]
可以看出,Person对象的属性和String数组的元素都被修改,说明参数内的属性或数组的修改会影响对象本身。具体可以打印地址再查看:
public static void main(String[] args) {
Person person = new Person("Rosy", 24);
String[] strings = {"AAA", "BBB", "CCC"};
System.out.println("第1次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
modifyObjAndPrintAddr(person, strings);
System.out.println("---------------------------");
System.out.println("第4次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
}
public static void modifyObjAndPrintAddr(Person person, String[] strings){
System.out.println("---------------------------");
System.out.println("第2次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
person.setAge(1024);
person.setName("ABC");
strings[0] = "XXX";
System.out.println("---------------------------");
System.out.println("第3次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
}
打印结果如下:
第1次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第2次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第3次打印:
990368553
1023892928
558638686
1831932724
1149319664
---------------------------
第4次打印:
990368553
2093631819
558638686
1831932724
1149319664
从地址上可以看出,person和strings的地址一直没有变过。在参数内部修改的person属性和数组元素,会对这部分成员的地址进行修改,并且会应用到对象本体上。
总结来说,无论传入的是基本类型还是引用类型,只要在方法内部尝试修改参数地址,只会在方法内部生效,不会影响对象本体。而在方法内部修改属性,会将相应的更改应用到对象本体上。因此,Java是值传递的。在传参时,不是将对象本身传入,而是创建一个副本。当被修改指向时,不会影响对象本身。由于不会修改对象本身的地址,因此属性的修改可以应用到对象本体上。
热门资讯