Java 函数的参数说
java函数参数传递的到底是值还是引用对确实容易让人迷糊。而很多时候因为对这个问题的模糊甚至造成一些错误。最常见的说法是基本类型传的是值,对象传的引用。对于基本类型,大家都达成共识,没有什么可以争论的。但对于对象传递,还有一说是也是值传递。首先来看一个例子。一个简单类person,只有一个属性name,和一个人事系统。如下所示:
public class Person{ private String name; public Persion(String name){ this.name = name; } public String getName(){ return this.name; } public void setName(String name){ this.name = name; } }
public class PersonnalSystem{ public static void changeName1(Persion person){ person.setName("Bob"); System.out.println("person name in changeName1: " person.getName());// Bob,被修改了 } public static void changeName2(Persion person){ Person anotherPerson = new Persion("Tom"); person = anotherPerson; System.out.println("person name in changeName2: " person.getName());// Tom被修改了 } public static void main(String[] agrs){ Person person = new Persion("Lily"); System.out.println("before change name person's name is"+person.getName);//Lily changeName2(person); System.out.println("after first change name person's name is"+person.getName);//被修改Bob changeName2(person); System.out.println("after second change name person's name is"+person.getName);//仍然是Bob,没有修改 } }
运行这个程序可以看到,changeName1修改了person的名字,确实是传递引用。但是当把person传递到changeName2中虽然在方法内修改成功,但main函数中仍然是Bob没有修改。这似乎又是传值了。这是因为,对象传递过程中传递的是对象的地址,而非对象的引用,也不是对象的副本。假设刚开始person的地址为60,changeName1接收到的参数是地址60,所以修改是在地址60的地方进行的,因此对象改变。而在changeName2中新建anotherPerson的地址也许是65,但绝非是60.当把anotherPerson赋值给person时,只是将person所代码的60改变成65,后续的修改操作都是在65处进行的,因此对main(60)中的person无影响。
所以总之来说我认为java参数传递过程是值传递。
- 基本类型传递值
- 引用类型传递的还是值,只不过是对象地址值,而非对象或副本。
这种方式对于String,Integer, Double等immutable类型时,也是符合的。因为这些对象不可变,因此每次传递的都是值。当然如果非要认为对象是引用传递也未尝不可,但是首先要区别String这类不可变对象,其次还要主义changeName2这种情况下千别希望原来对象被改变。