Ricerca…


Osservazioni

Questo dovrebbe aiutare a capire una "Eccezione puntatore nullo" - si ottiene uno di questi perché un riferimento all'oggetto è nullo, ma il codice del programma si aspetta che il programma utilizzi qualcosa in quel riferimento oggetto. Tuttavia, questo merita il proprio argomento ...

Riferimenti dell'oggetto come parametri del metodo

Questo argomento spiega il concetto di riferimento a un oggetto ; è rivolto a chi è nuovo alla programmazione in Java. Dovresti già avere familiarità con alcuni termini e significati: definizione della classe, metodo principale, istanza dell'oggetto e il richiamo dei metodi "su" un oggetto e passaggio dei parametri ai metodi.

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

Per essere completamente competente nella programmazione Java, dovresti essere in grado di spiegare questo esempio a qualcun altro in cima alla tua testa. I suoi concetti sono fondamentali per capire come funziona Java.

Come puoi vedere, abbiamo un main che istanzia un oggetto alla person variabile e chiama un metodo per impostare il campo del name in quell'oggetto su "Bob" . Quindi chiama un altro metodo e passa la person come uno dei due parametri; l'altro parametro è una variabile intera, impostata su 5.

Il metodo chiamato imposta il valore del name sull'oggetto passato su "Linda" e imposta la variabile intera passata a 99, quindi restituisce.

Quindi cosa verrebbe stampato?

Linda 5

Quindi, perché la modifica apportata alla person effetto main , ma la modifica apportata all'intero non lo è?

Quando viene effettuata la chiamata, il metodo principale passa un riferimento oggetto per person al metodo setPersonName ; qualsiasi modifica che setAnotherName apporta a quell'oggetto è parte di quell'oggetto e quindi tali modifiche fanno ancora parte dell'oggetto quando il metodo restituisce.

Un altro modo di dire la stessa cosa: la person punta a un oggetto (memorizzato sull'heap, se sei interessato). Qualsiasi modifica apportata dal metodo a quell'oggetto viene effettuata "su quell'oggetto" e non viene influenzata dal fatto che il metodo che esegue la modifica sia ancora attivo o sia ritornato. Quando il metodo ritorna, tutte le modifiche apportate all'oggetto sono ancora memorizzate su quell'oggetto.

Confrontalo con il numero intero che viene passato. Poiché questo è un primitivo int (e non un'istanza dell'oggetto Integer), viene passato "per valore", indicando che il suo valore è fornito al metodo, non un puntatore al numero intero originale passato. Il metodo può cambiarlo per il metodo propri scopi, ma ciò non influisce sulla variabile utilizzata quando viene effettuata la chiamata al metodo.

In Java, tutti i primitivi vengono passati per valore. Gli oggetti vengono passati per riferimento, il che significa che un puntatore all'oggetto viene passato come parametro a qualsiasi metodo che li preleva.

Una cosa meno ovvia questo significa: non è possibile per un metodo chiamato creare un nuovo oggetto e restituirlo come uno dei parametri. L'unico modo per un metodo per restituire un oggetto creato, direttamente o indirettamente, dalla chiamata al metodo, è come valore di ritorno dal metodo. Prima vediamo come non funzionerebbe, e poi come funzionerebbe.

Aggiungiamo un altro metodo al nostro piccolo esempio qui:

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

E, di nuovo nella parte main , sotto la chiamata a setAnotherName , chiamiamo questo metodo e un'altra chiamata println:

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

Ora il programma dovrebbe stampare:

Linda 5
Linda

Cosa è successo all'oggetto che aveva George? Bene, il parametro passato era un puntatore a Linda; quando il metodo getAnotherObjectNot creato un nuovo oggetto, ha sostituito il riferimento all'oggetto Linda con un riferimento all'oggetto George. L'oggetto Linda esiste ancora (nell'heap), il metodo main può ancora accedervi, ma il metodo getAnotherObjectNot non sarebbe in grado di fare nulla con esso dopo, perché non ha alcun riferimento ad esso. Sembrerebbe che lo scrittore del codice intendesse per il metodo creare un nuovo oggetto e passarlo indietro, ma se così fosse, non ha funzionato.

Se questo è ciò che lo scrittore voleva fare, avrebbe bisogno di restituire l'oggetto appena creato dal metodo, qualcosa del genere:

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

Quindi chiamalo così:

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

E l'intero output del programma ora sarebbe:

Linda 5
Linda
Mary

Ecco l'intero programma, con entrambe le aggiunte:

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow