Java 是值传递还是引用传递,又是怎么体现的
- 2024-09-09 福建
本文字数:5322 字
阅读完需:约 17 分钟
关于 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------------------------------------可以看到无论是基本类型还是引用类型,传参数进去的时候的值和执行完 modify 方法后的值是一样的,也就是第 1 次打印和第三次打印是一样的。可是为什么明明在第 2 次已经修改成功了,第 3 次却又变回去了呢?尝试换个方法把参数拿出来,
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:10modifyAndReturn第2次打印int:999------------------------------------modifyAndReturn第1次打印String:TommodifyAndReturn第2次打印String:ABC------------------------------------打印num:10打印name:Tom------------------------------------打印modifiedNum:999打印modifiedName:ABC可以看到通过 return 出来的值,的确是被改变了的,那又是为什么导致这个改变没有应用到参数本体呢?修改下代码再次测试
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)); }执行结果如下
修改前,传参前:1324119927990368553---------------------------修改前,传参后:1324119927990368553---------------------------修改后,传参后:10969792701078694789---------------------------修改后,执行完方法后:1324119927990368553可以看到传参进来的参数地址是和外部定义的地址是同一个,但是修改之后会指向另一个新的地址,导致原来地址上的数据不会受到影响,这其实是一个保护机制,防止参数传入方法内被篡改指向。
下面演示引用类型的另一种情况,一些老铁可能以为是对引用类型本身的修改,其实这是不对的。先定义一个类 Person
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 main5(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));
modifyObj(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)); }
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次打印:9903685531096979270107869478918319327241747585824---------------------------第2次打印:9903685531096979270107869478918319327241747585824---------------------------第3次打印:990368553102389292855863868618319327241149319664---------------------------第4次打印:990368553209363181955863868618319327241149319664从地址上可以看到,person 和 strings 的地址一直没有变过。而在参数内部修改的 person 属性和数组元素,会对这部分成员的地址进行修改,并且会应用到对象本体上。
总结下来就是,无论传的是基本类型还是引用类型,只要在方法内部尝试改变参数地址的,都只能在方法内部使用,不会影响本体,而在方法内部改变属性的,会把对应的改变应用到本体上。所以 Java 是值传递的,传参的时候并不是把本身传入,而是创建一个副本,当被修改指向的时候不会影响本身,修改属性由于不会修改本身的地址,因此的时候可以应用到本体上。
文章转载自:比花花解语
不在线第一只蜗牛
还未添加个人签名 2023-06-19 加入
还未添加个人简介







评论