Szukaj…


Uwagi

Powinno to pomóc w zrozumieniu „wyjątku zerowego wskaźnika” - jeden dostaje taki, ponieważ odwołanie do obiektu jest puste, ale kod programu oczekuje, że program użyje czegoś w tym odwołaniu do obiektu. To jednak zasługuje na własny temat ...

Odwołania do obiektu jako parametry metody

W tym temacie wyjaśniono pojęcie odwołania do obiektu ; jest skierowany do osób, które dopiero zaczynają programować w Javie. Powinieneś już znać kilka terminów i znaczeń: definicję klasy, metodę główną, instancję obiektu i wywoływanie metod „na” obiekcie oraz przekazywanie parametrów do metod.

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;
  }
}

Aby być w pełni kompetentnym w programowaniu w Javie, powinieneś być w stanie wyjaśnić ten przykład komuś spoza głowy. Jego koncepcje są fundamentalne dla zrozumienia, jak działa Java.

Jak widać, mamy element main który tworzy instancję obiektu dla zmiennej person i wywołuje metodę ustawiania pola name w tym obiekcie na "Bob" . Następnie wywołuje inną metodę i przekazuje person jako jeden z dwóch parametrów; drugim parametrem jest zmienna całkowita, ustawiona na 5.

Wywołana metoda ustawia wartość name przekazywanego obiektu na „Linda” i ustawia zmienną całkowitą przekazaną na 99, a następnie zwraca.

Co więc zostanie wydrukowane?

Linda 5

Dlaczego więc zmiana dokonana na person działa w main , a zmiana na liczbę całkowitą nie?

Po wywołaniu metoda główna przekazuje odwołanie do obiektu dla person do metody setPersonName ; każda zmiana wprowadzona przez setAnotherName w tym obiekcie jest częścią tego obiektu, a zatem zmiany te są nadal częścią tego obiektu, gdy metoda powróci.

Innym sposobem powiedzenia tego samego jest: person wskazuje na obiekt (przechowywany na stercie, jeśli jesteś zainteresowany). Wszelkie zmiany dokonane przez metodę na tym obiekcie są dokonywane „na tym obiekcie” i nie ma wpływu na to, czy metoda wprowadzająca zmianę jest nadal aktywna, czy powróciła. Gdy metoda powraca, wszelkie zmiany dokonane w obiekcie są nadal przechowywane w tym obiekcie.

Porównaj to z przekazaną liczbą całkowitą. Ponieważ jest to prymitywna int (a nie instancja obiektu typu Integer), jest przekazywana „przez wartość”, co oznacza, że jej wartość jest przekazywana do metody, a nie wskaźnik do przekazywanej oryginalnej liczby całkowitej. Metoda może ją zmienić dla metody własne cele, ale nie wpływa to na zmienną używaną podczas wywoływania metody.

W Javie wszystkie operacje podstawowe są przekazywane według wartości. Obiekty są przekazywane przez odniesienie, co oznacza, że wskaźnik do obiektu jest przekazywany jako parametr do wszystkich metod, które je przyjmują.

Oznacza to jedną mniej oczywistą rzecz: wywołana metoda nie może utworzyć nowego obiektu i zwrócić go jako jednego z parametrów. Jedynym sposobem, aby metoda zwróciła obiekt utworzony bezpośrednio lub pośrednio przez wywołanie metody, jest zwrócenie wartości z metody. Zobaczmy najpierw, jak to nie zadziała, a potem jak to będzie działać.

Dodajmy inną metodę do naszego małego przykładu tutaj:

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

I z powrotem w main , poniżej wywołania setAnotherName , setAnotherName tę metodę i kolejne wywołanie println:

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

Teraz program wydrukuje:

Linda 5
Linda

Co stało się z obiektem, który miał George? Cóż, przekazany parametr był wskaźnikiem do Lindy; gdy metoda getAnotherObjectNot utworzyła nowy obiekt, zastąpiła odwołanie do obiektu Linda odwołaniem do obiektu George. Obiekt Linda nadal istnieje (na stercie), main metoda nadal może uzyskać do niego dostęp, ale metoda getAnotherObjectNot nie byłaby w stanie nic z tym zrobić, ponieważ nie ma do niego odwołania. Wygląda na to, że autor kodu przeznaczony dla metody do utworzenia nowego obiektu i przekazania go z powrotem, ale jeśli tak, to nie działał.

Jeśli tego chciał pisarz, musiałby zwrócić nowo utworzony obiekt z metody, mniej więcej tak:

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

Następnie nazwij to tak:

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

Cały wynik programu byłby teraz:

Linda 5
Linda
Mary

Oto cały program z dwoma dodatkami:

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;
  }
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow