今天在看廖雪峰教程的时候,讲到了参数绑定,也是查了很多资料后理解了,这篇文章就是记录一下 java 中参数绑定的坑点。

基本类型参数的传递

  1. public class Main {
  2. public static void main(String[] args) {
  3. Person p = new Person();
  4. int n = 15; // n的值为15
  5. p.setAge(n); // 传入n的值
  6. System.out.println(p.getAge()); // 15
  7. n = 20; // n的值改为20
  8. System.out.println(p.getAge()); // 15
  9. }
  10. }
  11. class Person {
  12. private int age;
  13. public int getAge() {
  14. return this.age;
  15. }
  16. public void setAge(int age) {
  17. this.age = age;
  18. }
  19. }

从结果可知,修改外部的局部变量n,不影响实例page字段,原因是setAge()方法获得的参数,复制了n的值,因此,p.age和局部变量n互不影响。
结论:基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。

引用类型参数绑定

  1. public class Main {
  2. public static void main(String[] args) {
  3. Person p = new Person();
  4. String[] fullname = new String[] { "Homer", "Simpson" };
  5. p.setName(fullname); // 传入fullname数组
  6. System.out.println(p.getName()); // "Homer Simpson"
  7. fullname[0] = "Bart"; // fullname数组的第一个元素修改为"Bart"
  8. System.out.println(p.getName()); // "Bart Simpson"
  9. }
  10. }
  11. class Person {
  12. private String[] name;
  13. public String getName() {
  14. return this.name[0] + " " + this.name[1];
  15. }
  16. public void setName(String[] name) {
  17. this.name = name;
  18. }
  19. }

注意到setName()的参数现在是一个数组。一开始,把fullname数组传进去,然后,修改fullname数组的内容,结果发现,实例p的字段p.name也被修改了!
Java中的参数绑定机制 - 图1
结论:引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方(因为指向同一个对象嘛)。

特例:String

  1. public class Main {
  2. public static void main(String[] args) {
  3. Person p = new Person();
  4. String bob = "Bob";
  5. p.setName(bob); // 传入bob变量
  6. System.out.println(p.getName()); // "Bob"
  7. bob = "Alice"; // bob改名为Alice
  8. System.out.println(p.getName()); // "Bob"
  9. }
  10. }
  11. class Person {
  12. private String name;
  13. public String getName() {
  14. return this.name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. }

这里第二次还是输出“Bob”。
首先这里引用参数绑定的机制是没有问题的。正常来说,第二次应该输出“Alice”,但是他却输出了“Bob”。是因为String类型的问题。因为String是不可变的(看源码会发现String类是被final修饰的)

所以,第七行代码这里修改变量bob,实际上是bob的指向更新了,指向了“Alice”。而原来的内存还是没有变,还是“Bob”,而且p.name指向的还是“Bob”(因为bob是重新new了一个示例,与p.name没有关系)
Java中的参数绑定机制 - 图2