Zoeken…


Opmerkingen

Dit zou je moeten helpen een "Null Pointer Exception" te begrijpen - je krijgt er een omdat een objectverwijzing null is, maar de programmacode verwacht dat het programma iets in die objectverwijzing gebruikt. Dat verdient echter een eigen onderwerp ...

Objectverwijzingen als methodeparameters

In dit onderwerp wordt het concept van een objectverwijzing uitgelegd; het is gericht op mensen die nog maar net in Java programmeren. Je zou al bekend moeten zijn met enkele termen en betekenissen: klassedefinitie, hoofdmethode, objectinstantie en het aanroepen van methoden op een object en het doorgeven van parameters aan methoden.

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

Om volledig bekwaam te zijn in het programmeren van Java, moet u dit voorbeeld aan iemand anders uit uw hoofd kunnen uitleggen. De concepten zijn fundamenteel om te begrijpen hoe Java werkt.

Zoals u kunt zien, hebben we een main dat een object aan de variabele instantie van person , en roept een methode om de set name veld in dat object aan "Bob" . Vervolgens roept het een andere methode aan en geeft deze person als een van de twee parameters; de andere parameter is een integer variabele, ingesteld op 5.

De methode genaamd stelt de name waarde op de doorgegeven object "Linda, en stelt de integervariabele doorgegeven aan 99, dan terug.

Dus wat zou er worden afgedrukt?

Linda 5

Dus waarom wordt de wijziging die in de person wordt aangebracht in de main kracht, maar de wijziging in het gehele getal niet?

Wanneer de oproep wordt gedaan, geeft de setPersonName een objectverwijzing voor person aan de methode setPersonName ; elke wijziging die setAnotherName in dat object setAnotherName maakt deel uit van dat object, en dus maken die wijzigingen nog steeds deel uit van dat object wanneer de methode terugkeert.

Een andere manier om hetzelfde te zeggen: person wijst naar een object (opgeslagen op de heap, als je geïnteresseerd bent). Elke wijziging die de methode in dat object aanbrengt, wordt "op dat object" aangebracht en wordt niet beïnvloed door het feit of de methode die de wijziging aanbrengt nog steeds actief is of is teruggekeerd. Wanneer de methode terugkeert, worden wijzigingen die aan het object zijn aangebracht, nog steeds in dat object opgeslagen.

Vergelijk dit met het gehele getal dat wordt doorgegeven. Aangezien dit een primitieve int is (en geen instantie van een Integer-object), wordt het "door waarde" doorgegeven, wat betekent dat de waarde ervan aan de methode wordt doorgegeven, geen verwijzing naar het oorspronkelijke doorgegeven gehele getal. De methode kan deze wijzigen voor de methode eigen doeleinden, maar dat heeft geen invloed op de variabele die wordt gebruikt wanneer de methode wordt aangeroepen.

In Java worden alle primitieven doorgegeven aan waarde. Objecten worden doorgegeven door verwijzing, wat betekent dat een aanwijzer naar het object wordt doorgegeven als de parameter voor alle methoden die ze gebruiken.

Een minder voor de hand liggend ding betekent dit: het is niet mogelijk voor een aangeroepen methode om een nieuw object te maken en terug te geven als een van de parameters. De enige manier voor een methode om een object te retourneren dat direct of indirect door de methode-aanroep is gemaakt, is als een retourwaarde van de methode. Laten we eerst kijken hoe dat niet zou werken en dan hoe het zou werken.

Laten we hier nog een methode toevoegen aan ons kleine voorbeeld:

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

En, terug in het main , onder de aanroep van setAnotherName , laten we deze methode en een andere println-aanroep aanroepen:

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

Nu zou het programma afdrukken:

Linda 5
Linda

Wat gebeurde er met het object dat George had? Nou, de parameter die werd doorgegeven was een wijzer naar Linda; Toen de methode getAnotherObjectNot een nieuw object maakte, verving het de verwijzing naar het Linda-object door een verwijzing naar het George-object. De Linda object bestaat nog steeds (op de heap), de main methode nog steeds toegang, maar de getAnotherObjectNot methode niet zou kunnen doen met het na dat, omdat het geen verwijzing ernaar. Het lijkt erop dat de schrijver van de code bedoeld was voor de methode om een nieuw object te maken en terug te geven, maar als dat zo was, werkte het niet.

Als dat is wat de schrijver wilde doen, zou hij het nieuw gecreëerde object van de methode moeten retourneren, zoiets als dit:

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

Noem het dan zo:

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

En de volledige output van het programma zou nu zijn:

Linda 5
Linda
Mary

Hier is het hele programma, met beide toevoegingen:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow