Java 是“按引用传递”还是“按值传递”?这是最近stackoverflow上关注度比较高的问题。其中一个大佬的回答是这样:
Java 总是按值传递参数,而不是按引用。
让我通过一个例子来解释这一点:
public class Main {
public static void main(String[] args) {
Foo f = new Foo("f");
changeReference(f); // 它不会改变引用!
modifyReference(f); // 它将修改引用变量“f”所指的对象!
}
public static void changeReference(Foo a) {
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c) {
c.setAttribute("c");
}
}
我将分步骤解释这一点:
-
声明一个名为
f
type的引用,Foo
并为其分配一个Foo
具有属性的 type 新对象"f"
。Foo f = new Foo("f");
-
在方法方面,声明
Foo
了一个具有名称的类型的引用,a
并且它最初被赋值为null
。public static void changeReference(Foo a)
-
当您调用该方法时
changeReference
,该引用a
将被分配作为参数传递的对象。changeReference(f);
-
声明一个名为
b
type的引用,Foo
并为其分配一个Foo
具有属性的 type 新对象"b"
。Foo b = new Foo("b");
-
a = b
使新的分配到引用a
,不是f
,其属性是对象的"b"
。 -
当您调用
modifyReference(Foo c)
方法时,c
会创建一个引用并分配给具有属性的对象"f"
。 -
c.setAttribute("c");
将更改引用c
指向它的对象的属性,并且引用指向它的是同一个对象f
。
我希望你现在明白在 Java 中将对象作为参数是如何工作的 :)
如果你还是不明白,我再举个栗子,你可以在开发工具中引入这两个类:
/**
* <p>
* 猫类
* </p>
*
* @author simple
* @since 2021年09月03日
*/
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* <p>
* 测试类
* </p>
*
* @author simple
* @since 2021年09月03日
*/
public class Main {
public static void main(String[] args) {
Cat myCat = new Cat("One");
System.out.println("One`s addr: " + myCat);
change(myCat);
System.out.println("Last addr: " + myCat);
System.out.println("Last name: " + myCat.getName());
}
private static void change(Cat cat) {
cat.setName("Two");
System.out.println("Two`s addr: " + cat);
cat = new Cat("Three");
System.out.println("Three`s addr: " + cat);
cat.setName("Four");
System.out.println("Four`s addr: " + cat);
}
}
运行后的结果是:
从结果可以看出,chang()方法只是改变了原来的值,并没有改变堆地址。