Pregunta

Tengo un constructor como el siguiente:

public Agent(){

    this.name = "John";
    this.id = 9;
    this.setTopWorldAgent(this, "Top_World_Agent", true);

}

Recibo una excepción de puntero nulo aquí en la llamada al método.Parece ser porque estoy usando 'esto' como argumento en el método setTopWorldAgent.Al eliminar la llamada a este método, todo parece estar bien.¿Por qué pasó esto?Alguien más ha experimentado esto?

¿Fue útil?

Solución

Puedes pasar esto a métodos, pero setTopWorldAgent() no puede ser abstracto.No puedes realizar una llamada virtual en el constructor.

En el constructor de un objeto, puede llamar a métodos definidos en ese objeto o clases base, pero no puede esperar llamar a algo que será proporcionado por una clase derivada, porque partes de la clase derivada aún no están construidas.Habría esperado algún tipo de error del compilador si setTopWorldAgent() fuera abstracto.

En Java, puede obtener un comportamiento sorprendente con el constructor y las clases derivadas: aquí hay un ejemplo.

http://en.wikipedia.org/wiki/Virtual_functions#Java_3

Si está acostumbrado a C# o C++, podría pensar que es seguro llamar a funciones virtuales y no llamar a funciones anuladas.En Java, la llamada virtual se realiza aunque la clase derivada no esté completamente construida.

Si esto no es lo que está sucediendo, entonces presumiblemente, todas las partes de esto que setTopWorldAgent() necesita están inicializadas; si no, probablemente sea uno de los miembros de esto el que necesita ser inicializado.

Editar:Pensé que esto era C#

Otros consejos

Por curiosidad, ¿por qué pasas 'esto' a una función miembro de la misma clase?setTopWorldAgent() puede usar 'esto' directamente.No parece que su constructor o setTopWorldAgent() sean estáticos, por lo que no estoy seguro de por qué pasaría una función miembro a algo a lo que ya tiene acceso.

A menos que me esté perdiendo algo...

¿Por qué setTopWorldAgent necesidad this como argumento?Según la invocación, es un método de instancia, por lo que podría hacer referencia this sin necesidad de recibirlo como parámetro.

Creo que más concretamente, ¿por qué diablos estás pasando 'esto' como parámetro a un método en 'esto'?

Lo siguiente probaría lo que dices que te está sucediendo y no tengo problemas con eso.

public class Test {
  public Test() {
    this.hi(this);
  }
  public void hi(Test t) {
    System.out.println(t);
  }

  public static void main(String[] args) throws Exception {
    Test t = new Test();
  }
}

Dado que setTopWorldAgent parece ser un método de instancia, ¿por qué le estás pasando esto de todos modos?

"esto" nunca debe ser nulo.¿Estás seguro de que se lanza la excepción por eso?

Algo a tener en cuenta es que si el método es virtual o llama a algún método virtual, entonces se podría ejecutar un método que pertenece a una subclase antes de que se inicialicen las variables de la subclase.

El error debe estar en otra parte porque el código anterior definitivamente funciona, la referencia nula debe ser otra cosa.

Si su agente está implementando ITopWorldAgent, entonces debería hacer esto:


Agent agent = new Agent("John", 9);
agent.setTopWorldAgent(agent, "Top_World_Agent", true);

Si no es así, ¿por qué estás configurando algo de la forma en que lo estás haciendo?

Supongo que algo en el método setTopWorldAgent está usando un valor que aún no se ha inicializado en su constructor.

this no es nulo, eso es seguro.Ha sido asignado.

Dicho esto, no es necesario pasar. this en el método, está disponible automáticamente en todos los métodos de instancia.Si el método es estático, es posible que desee refactorizarlo y convertirlo en un método de instancia.

Las reglas de Java establecen que nunca debes pasar 'esto' a otro método desde su constructor, por la sencilla razón de que el objeto no ha sido completamente construido.El objeto al que hace referencia puede estar en un estado inconsistente.Me sorprende que la referencia real a 'esto' sea nula, pero no me sorprende en absoluto que algún miembro de 'esto' sea nulo cuando se pasa a setTopWorldAgent, y que el método arroje la excepción debido a esto.

Por lo general, puede salirse con la suya pasando 'esto' desde los constructores siempre y cuando no acceda a ningún miembro ni llame a métodos, por ejemplo, si desea establecer una referencia a 'esto' en otro objeto.

En este caso, por supuesto, el argumento es innecesario ya que el método ya tiene una referencia a "esto".

Me alegra que hayas obtenido una respuesta.Me gustaría agregar que pasar 'esto' como parámetro puede generar problemas de concurrencia inesperados.Básicamente, está brindando la posibilidad de que el estado del objeto sea manipulado de manera insegura mediante un código potencialmente no seguro para subprocesos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top