对象引用作为方法参数

本主题解释了对象引用的概念 ; 它面向那些刚接触 Java 编程的人。你应该已经熟悉了一些术语和含义:类定义,主方法,对象实例,以及在对象上调用方法,以及将参数传递给方法。

public class Person {

  private String name;

  public void setName(String name) { this.name = name; }

  public String getName() { return name; }

  public static void main(String [] arguments) {
    Person person = new Person();
    person.setName("Bob");

    int i = 5;
    setPersonName(person, i);

    System.out.println(person.getName() + " " + i);
  }

  private static void setPersonName(Person person, int num) {
    person.setName("Linda");
    num = 99;
  }
}

要完全胜任 Java 编程,你应该能够向其他人解释这个例子。它的概念是理解 Java 如何工作的基础。

如你所见,我们有一个 main,它将一个对象实例化为变量 person,并调用一个方法将该对象中的 name 字段设置为 Bob。然后它调用另一个方法,并将 person 作为两个参数之一传递; 另一个参数是整数变量,设置为 5。

调用的方法将传递的对象上的 name 值设置为 Linda,并将传递给的整数变量设置为 99,然后返回。

那会打印什么?

Linda 5

那么为什么对 person 的更改在 main 中生效,但是对整数的改变不是?

调用时,main 方法将 person对象引用传递给 setPersonName 方法; setAnotherName 对该对象所做的任何更改都是该对象的一部分,因此当该方法返回时,这些更改仍然是该对象的一部分。

另一种说法相同的方式:person 指向一个对象(存储在堆上,如果你感兴趣的话)。方法对该对象所做的任何更改都是在该对象上进行的,并且不受进行更改的方法是否仍处于活动状态或已返回的影响。方法返回时,对对象所做的任何更改仍存储在该对象上。

将此与传递的整数进行对比。由于这是一个原始 int(而不是一个 Integer 对象实例),它是按值传递的,这意味着它的值被提供给方法,而不是指向传入的原始整数的指针。该方法可以为方法的更改自己的目的,但这不会影响进行方法调用时使用的变量。

在 Java 中,所有原语都是按值传递的。对象通过引用传递,这意味着指向对象的指针作为参数传递给任何接受它们的方法。

这意味着一个不太明显的事情:被调用的方法不可能创建一个对象并将其作为参数之一返回。方法返回由方法调用直接或间接创建的对象的唯一方法是作为方法的返回值。让我们首先看看它是如何工作的,然后是如何工作的。

让我们在这里给我们的小例子添加另一种方法:

private static void getAnotherObjectNot(Person person) {
  person = new Person();
  person.setName("George");
}

而且,回到 main,在 setAnotherName 的调用之下,让我们调用这个方法和另一个 println 调用:

getAnotherObjectNot(person);
System.out.println(person.getName());

现在该程序将打印出来:

Linda 5
Linda

乔治的物体怎么了?好吧,传入的参数是指向 Linda 的指针; 当 getAnotherObjectNot 方法创建了一个新对象时,它使用对 George 对象的引用替换了对 Linda 对象的引用。Linda 对象仍然存在(在堆上),main 方法仍然可以访问它,但是 getAnotherObjectNot 方法之后将无法对它做任何事情,因为它没有引用它。看起来代码的编写者打算为方法创建一个新对象并将其传回去,但如果是这样,它就不起作用了。

如果这是作者想要做的,他将需要从方法返回新创建的对象,如下所示:

private static Person getAnotherObject() {
  Person person = new Person();
  person.setName("Mary");
  return person;
}

然后这样称呼它:

Person mary;
mary = getAnotherObject();
System.out.println(mary.getName());

整个程序输出现在将是:

Linda 5
Linda
Mary

这是整个程序,增加了两个:

public class Person {
  private String name;

  public void setName(String name) { this.name = name; }
  public String getName() { return name; }

  public static void main(String [] arguments) {
    Person person = new Person();
    person.setName("Bob");

    int i = 5;
    setPersonName(person, i);
    System.out.println(person.getName() + " " + i);
    
    getAnotherObjectNot(person);
    System.out.println(person.getName());
    
    Person person;
    person = getAnotherObject();
    System.out.println(person.getName());
  }
  
  private static void setPersonName(Person person, int num) {
    person.setName("Linda");
    num = 99;
  }
  
  private static void getAnotherObjectNot(Person person) {
    person = new Person();
    person.setMyName("George");
  }
  
  private static person getAnotherObject() {
    Person person = new Person();
    person.setMyName("Mary");
    return person;
  }
}