Buscar..


Observaciones

Esto debería ayudarlo a comprender una "excepción de puntero nulo": uno de ellos obtiene uno porque una referencia de objeto es nula, pero el código del programa espera que el programa use algo en esa referencia de objeto. Sin embargo, eso merece su propio tema ...

Referencias de objetos como parámetros del método.

Este tema explica el concepto de una referencia de objeto ; Está dirigido a personas que son nuevas en la programación en Java. Ya debe estar familiarizado con algunos términos y significados: definición de clase, método principal, instancia de objeto y la llamada de métodos "en" un objeto, y pasar parámetros a los métodos.

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

Para ser plenamente competente en la programación de Java, debería poder explicar este ejemplo a alguien que no esté en lo alto de su cabeza. Sus conceptos son fundamentales para entender cómo funciona Java.

Como puede ver, tenemos un main que crea una instancia de un objeto para la person variable y llama a un método para establecer el campo de name en ese objeto en "Bob" . Luego llama a otro método y pasa a la person como uno de dos parámetros; el otro parámetro es una variable entera, establecida en 5.

El método llamado establece el valor del name en el objeto pasado a "Linda", y establece la variable entera pasada a 99, luego regresa.

Entonces, ¿qué se imprimiría?

Linda 5

Entonces, ¿por qué el cambio realizado en person tiene efecto en main , pero el cambio realizado en el entero no lo hace?

Cuando se realiza la llamada, el método principal pasa una referencia de objeto por person al método setPersonName ; cualquier cambio que setAnotherName haga a ese objeto es parte de ese objeto, por lo que esos cambios aún son parte de ese objeto cuando el método regresa.

Otra forma de decir lo mismo: la person apunta a un objeto (almacenado en el montón, si está interesado). Cualquier cambio que el método haga a ese objeto se realiza "en ese objeto", y no se ve afectado por si el método que realiza el cambio todavía está activo o ha regresado. Cuando el método vuelve, cualquier cambio realizado en el objeto todavía se almacena en ese objeto.

Contrasta esto con el entero que se pasa. Dado que este es un int primitivo (y no una instancia de objeto Integer), se pasa "por valor", lo que significa que su valor se proporciona al método, no un puntero al entero original pasado. El método puede cambiarlo por el método propósitos propios, pero eso no afecta a la variable utilizada cuando se realiza la llamada al método.

En Java, todas las primitivas se pasan por valor. Los objetos se pasan por referencia, lo que significa que un puntero al objeto se pasa como parámetro a cualquier método que los tome.

Esto significa algo menos obvio: no es posible que un método llamado cree un nuevo objeto y lo devuelva como uno de los parámetros. La única forma en que un método puede devolver un objeto que se crea, directa o indirectamente, mediante la llamada al método, es como un valor de retorno del método. Primero veamos cómo eso no funcionaría, y luego cómo funcionaría.

Agreguemos otro método a nuestro pequeño ejemplo aquí:

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

Y, de nuevo en la parte main , debajo de la llamada a setAnotherName , pongamos una llamada a este método y otra llamada println:

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

Ahora el programa se imprimiría:

Linda 5
Linda

¿Qué pasó con el objeto que tenía George? Bueno, el parámetro que se pasó fue un indicador a Linda; cuando el método getAnotherObjectNot creó un nuevo objeto, reemplazó la referencia al objeto de Linda con una referencia al objeto de George. El objeto de Linda todavía existe (en el montón), el método main todavía puede acceder a él, pero el método getAnotherObjectNot no podría hacer nada con él después de eso, porque no tiene ninguna referencia a él. Parece que el autor del código destinado al método crea un nuevo objeto y lo devuelve, pero si es así, no funciona.

Si eso es lo que el escritor quería hacer, tendría que devolver el objeto recién creado desde el método, algo como esto:

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

Entonces llámalo así:

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

Y la salida del programa completo ahora sería:

Linda 5
Linda
Mary

Aquí está el programa completo, con ambas adiciones:

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow